现在的位置: 首页 > 综合 > 正文

GCC后端及汇编发布(4)

2013年10月27日 ⁄ 综合 ⁄ 共 7776字 ⁄ 字号 评论关闭

3.       



genrecog
工具

3.1.



代码输出的准备

工具
genrecog
用于产生识别及转换
RTL
到汇编的转换引擎。在这里我们看到该工具如何从机器描述文件构建出这个引擎——我们以
i386
系统为例子,这个机器描述文件是
i386.md

 

2612


int

2613


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

2614


{

2615


 
rtx desc;

2616


 
struct
decision_head
recog_tree, split_tree, peephole2_tree,
h;

2617

2618


 
progname

= "genrecog";

2619

2620


 
memset (&recog_tree, 0, sizeof
recog_tree);

2621


 
memset (&split_tree, 0, sizeof
split_tree);

2622


 
memset (&peephole2_tree, 0, sizeof
peephole2_tree);

2623

2624


 
if (argc <= 1)

2625


   
fatal ("no input file name");

 


2616
行,结构体
decision_head
保存了转换引擎的决策树(
decision tree
)。它具有如下的定义。

 


73   


struct
decision_head                                                                                   
in genrecog.c

74   


{

75   


 
struct

decision
*first;

76   


 
struct

decision
*last;

77   


};

 

而在上面
75
行,
decision

的定义如下。

 


125 


struct
decision                                                                                    
      
in genrecog.c

126 


{

127 


 

struct
decision_head
success;    
/*
Nodes to test on success. 
*/

128 


 

struct
decision *next;      
/* Node to
test on failure. 
*/

129 


 

struct
decision *prev;      
/* Node whose
failure tests us. 
*/

130 


 

struct
decision *afterward;  
 
/* Node to test on success,

131 


                           
  
        
 
 
 
but failure of successor nodes. 
*/

132 

133 


 

const
char *position;        
/* String
denoting position in pattern. 
*/

134 

135 


 
struct
decision_test
*tests; 
/* The tests for this node. 

*/

136 

137 


 

int number;              
/* Node number, used for labels */

138 


 

int subroutine_number;     
/* Number of subroutine this node starts */

139 


 

int need_label;   
           
/* Label
needs to be output. 
*/

140 


};

 


135
行,
decision_test

保存了决策所需要的测试及其结果。

 


83   


struct
decision_test                                                                             
      
in genrecog.c

84   


{

85   


 

/* A linked list through the tests attached to
a node. 
*/

86   


 

struct
decision_test *next;

87   

88   


 

/* These types are roughly in the order in
which we'd like to test them. 
*/

89   


 


enum
decision_type

90   


 

{

91   


   

DT_mode, DT_code, DT_veclen,

92   


   

DT_elt_zero_int, DT_elt_one_int, DT_elt_zero_wide,
DT_elt_zero_wide_safe,

93   


   
DT_veclen_ge, DT_dup, DT_pred,
DT_c_test,

94   


   
DT_accept_op, DT_accept_insn

95   


 
} type;

96   

97   


 
union

98   


 
{

99   


   
enum
machine_mode mode; 
/* Machine mode of node. 

*/

100 


   
RTX_CODE code;          
/* Code to
test. 


*/

101 

102 


   

struct

103 


   

{

104 


     

const
char *name;         
/*
Predicate to call. 
*/

105 


     

int index;   
               
/*
Index into `preds' or -1. 
*/

106 


     

enum
machine_mode mode;     
/* Machine mode
for node. 
*/

107 


   

} pred;

108 

109 


   

const
char *c_test;          
/*
Additional test to perform. 
*/

110 


   

int veclen;                
/* Length of vector. 

*/

111 


   

int dup;  
                  
/*
Number of operand to compare against. 
*/

112 


   

HOST_WIDE_INT intval;   
/* Value for XINT for XWINT. 
*/

113 


   

int opno;          
       
/* Operand
number matched. 
*/

114 

115 


   

struct
{

116 


     

int code_number;        
/* Insn number matched. 

*/

117 


     

int lineno;  
              
/*
Line number of the insn. 
*/

118 


     

int num_clobbers_to_add; 
/* Number of CLOBBERs to be added. 
*/

119 


   

} insn;

120 


 

} u;

121 


};

 

首先我们初始化
recog_tree


split_tree


peephole2_tree


h

的所有
decision_head
实例为
0
。然后需要初始化读入器来读入机器描述文件(
md
文件)。

 

main (continued, genrecog)

 

2627


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

2628


   
return
(FATAL_EXIT_CODE);

2629

2630


 
next_insn_code

= 0;

2631


 
next_index

= 0;

2632

2633


 
write_header ();

 


2627
行,函数
init_md_reader_args


处理命令行选项。对于
genrecog
工具,它仅接受
-I
选项。这个选项显示了查找
md
文件的附加路径。然后该函数调用
init_md_reader


。这个函数我们已经在
genconditions工具



一节中看过。它从
md
文件中读入模式,构建相应的
rtx
对象并链入指定的链表。

注意到在
init_md_reader


的从
928

933
行,
genrecog
现在把由
genconditions
构建的
insn-conditions

放入哈希表
condition_table

中。并且记住访问的次序是:
define_attr

define_insn
,然后其它。

3.2.



读入
rtl
形式的定义

3.2.1.


选择合适的模式

所有的工具都有这一步,不过对于除
genconditions
以外的其它工具,可以进行一些优化,因为它们可以,通过由
genconditions
产生的
insn_conditions

,过滤出不活动的模式。

 

main (continued, genrecog)

 

2635


 
/* Read the machine
description. 
*/

2636

2637


 
while
(1)

2638


 
{

2639


   
desc = read_md_rtx
(&pattern_lineno

,
&next_insn_code

);

2640


   
if (desc == NULL)

2641


     
break
;

2642

2643


   
if (GET_CODE (desc) == DEFINE_INSN)

2644


   
{

2645


    
 
h =
make_insn_sequence
(desc, RECOG);

2646


   
  
merge_trees
(&recog_tree, &h);

2647


 
  
}

2648


   
else if (GET_CODE (desc) == DEFINE_SPLIT)

2649


   
{

2650


   
  
h =
make_insn_sequence
(desc, SPLIT);

2651


   
  
merge_trees
(&split_tree, &h);

2652


   
}

2653


   
else if (GET_CODE (desc) ==
DEFINE_PEEPHOLE2)

2654


   
{

2655


   
  
h =
make_insn_sequence
(desc, PEEPHOLE2);

2656


   
  
merge_trees
(&peephole2_tree, &h);

2657


   
}

2658

2659


   
next_index

++;

2660


 
}

 


genconditions工具



一节我们已经碰到了
read_md_rtx


,现在我们仔细看一下它做什么。

 

965 


rtx


966 


read_md_rtx (int
*lineno, int *seqnr)                              
      
             
in
gensupport.c

967 


{

968 


 

struct
queue_elem **queue, *elem;

969 


 

rtx desc;

970 

971 


discard:

972 

973 


 

/* Read all patterns from a given queue before
moving on to the next. 
*/

974 


 

if (define_attr_queue

!= NULL)

975 


   

queue = &define_attr_queue

;

976 


 

else if (define_insn_queue

!= NULL)

977 


   

queue = &define_insn_queue

;

978 


 

else if (other_queue != NULL)

979 


   

queue = &other_queue

;

980 


 

else

981 


   

return
NULL_RTX;

982 

983 


 

elem = *queue;

984 


 

*queue = elem->next;

985 


 

desc = elem->data;

986 


 

read_rtx_filename

= elem->filename;

987 


 

*lineno = elem->lineno;

988 


 

*seqnr = sequence_num

;

989 

990 


 

free (elem);

991 

992 


 

/* Discard insn patterns which we know can
never match (because

993 


   
their C test is provably always false). If
insn_elision is

994 


   
false, our caller needs to see all the
patterns. Note that the

995 


   
elided patterns are never counted by the
sequence numbering; it

996 


   
it is the caller's responsibility, when
insn_elision is false, not

997 


   
to use elided pattern numbers for
anything. 
*/

998 


 

switch
(GET_CODE (desc))

999 


 

{

1000


   
case
DEFINE_INSN:

1001


   
case
DEFINE_EXPAND:

1002


     
if (maybe_eval_c_test
(XSTR (desc, 2)) != 0)

1003


       
sequence_num

++;

1004


     
else if (insn_elision

)

1005


       
goto

discard;

1006


     
break
;

1007

1008


   
case
DEFINE_SPLIT:

1009


   
case
DEFINE_PEEPHOLE:

1010


   
case
DEFINE_PEEPHOLE2:

1011


     
if (maybe_eval_c_test
(XSTR (desc, 1)) != 0)

1012


       
sequence_num

++;

1013


     
else if (insn_elision

)

1014


       
goto
discard;

1015


     
break
;

1016

1017


   
default
:

1018


     
break
;

1019


 
}

1020

1021


 
return
desc;

1022


}

 


genrecog
中,
maybe_eval_c_test


可能为模式执行非平凡(
non-trivial
)的测试。

 

1067


int


1068


maybe_eval_c_test (const
char *expr)                                                  
in
gensupport.c

1069


{

1070


 
const
struct
c_test *test;

1071


 
struct
c_test
dummy;

1072

1073


 
if (expr[0] == 0)

1074


   
return
1;

1075

1076


 
if (insn_elision_unavailable)

1077


   
return
-1;

1078

1079


 
dummy.expr = expr;

1080


 
test = htab_find (condition_table

, &dummy);

1081


 
if (!test)

1082


   
abort ();

1083

1084


 
return
test->value;

1085


}

 

注意到在
1084
行,
test


condtion_table

获取,其内容来自由
genconditions
产生的
insn_condition

,正如我们在
init_md_reader


看到那样。
test


value


genconditions工具



一节中确定。在
write_one_condition



157
行,
value


MAYBE_EVAL(expr)
返回。
MAYBE_EVAL
也是由
genconditions
按以下方式定义:

 

123 


puts ("/                                                                                              
in
genconditions.c

124 


/* If we don't have
__builtin_constant_p, or it's not acceptable in/n/

125 


 
array initializers, fall back to assuming
that all conditions/n/

126 


 
potentially vary at run time. It works in 3.0.1
and later; 3.0/n/

127 


 
only when not optimizing. 
*/

/n/

128 


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

129 


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

130 


#else
/n/

131 


# define

MAYBE_EVAL(expr) -1/n/

132 


#endif
/n");

 

__builtin_constant_p

返回整数
1
,如果该参数已知是一个编译时常量;返回
0
,如果它不能确定为编译时常量。一个
0
返回值不表示这个值不是一个常量,仅是表明
GCC
不能证明,在给定的
-O
选项(优化)值下,它是一个常量。

因此在
read_md_rtx



1011
行,在工具处理这个机器描述文件过程中,跳过那些条件测试部分已知为
false
的模式。这可以节省处理时间,并减小产生出来文件的大小。而那些条件测试部分已知为
true
,或那些条件测试部分不能确信为常量的模式,为
read_md_rtx


返回,并将由
make_insn_sequence


处理。

 

2413


static
struct
decision_head


2414


make_insn_sequence (rtx insn, enum
routine_type type)                                
in
genrecog.c

2415


{

2416


 
rtx x;

2417


 
const
char *c_test
= XSTR (insn, type == RECOG ? 2 : 1);

2418


 
int truth = maybe_eval_c_test
(c_test);

2419


 
struct
decision *last;

2420


 
struct
decision_test *test, **place;

2421


 
struct
decision_head head;

2422


 
char c_test_pos[2];

2423

2424


 
/* We should never
see an insn whose C test is false at compile time. 
*/

2425


 
if (truth == 0)

2426


   
abort ();

2427

抱歉!评论已关闭.