GCC后端及汇编发布(35)

9.6.4. 输出自动机数据

自动机的生成一节,我们已经看到在自动机的产生过程中,构建了许多数据。现在是时候为这些数据输出代码了。

 

9867 void

9868 write_automata (void)                                                                         ingenautomata.c

9869 {

9870   if (progress_flag)

9871     fprintf (stderr, "done\n");

9872   if (have_error)

9873     fatal ("Errors in DFAdescription");

9874   ticker_on (&all_time);

9875   output_time = create_ticker ();

9876   if (progress_flag)

9877     fprintf (stderr, "Forming andoutputting automata tables...");

9878   output_dfa_max_issue_rate();

9879   output_tables();

9880   if (progress_flag)

9881   {

9882     fprintf (stderr, "done\n");

9883     fprintf (stderr, "Output functions towork with automata...");

9884   }

 

在9878行,output_dfa_max_issue_rate确定max_dfa_issue_rate的值,这个变量通过宏MAX_DFA_ISSUE_RATE来访问。其值等于在define_insn_reservation中描述的所有指令,这些指令可以在同一个处理器周期内发布。

 

7090 static void

7091 output_dfa_max_issue_rate (void)                                                               ingenautomata.c

7092 {

7093   automaton_tautomaton;

7094

7095   if (UNDEFINED_LONGEST_PATH_LENGTH ==ON_THE_PATH || ON_THE_PATH >= 0)

7096     abort ();

7097   max_dfa_issue_rate = 0;

7098   for(automaton = description->first_automaton;

7099       automaton != NULL;

7100       automaton = automaton->next_automaton)

7101     pass_states(automaton, process_state_longest_path_length);

7102   fprintf (output_file, "\nint %s = %d;\n",

7103          MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);

7104 }

 

上面UNDEFINED_LONGEST_PATH_LENGTH被定义为1,ON_THE_PATH被定义为2。

 

7072 static void

7073 process_state_longest_path_length (state_t state)                                     ingenautomata.c

7074 {

7075   int value;

7076

7077   value = longest_path_length(state);

7078   if (value > max_dfa_issue_rate)

7079     max_dfa_issue_rate = value;

7080 }

 

我们已经看到在这里指令发布驱动自动机。并且伪指令advance_cycle_insn_decl推进CPU一个周期。因此longest_path_length找出可以在一个周期内1的最大指令数。这个值在上面7079行被保存入max_dfa_issue_rate

 

7034 static int

7035 longest_path_length (state_tstate)                                                        ingenautomata.c

7036 {

7037   arc_t arc;

7038   int length, result;

7039

7040   if (state->longest_path_length ==ON_THE_PATH)

7041     /* We don'texpect the path cycle here. Our graph may contain

7042       only cycles with one state on the pathnot containing `cycle

7043       advance' arcs -- see comment below.  */

7044     abort ();

7045   else if (state->longest_path_length !=UNDEFINED_LONGEST_PATH_LENGTH)

7046     /* We alreadyvisited the state.  */

7047     returnstate->longest_path_length;

7048

7049   result = 0;

7050   for (arc =first_out_arc (state); arc != NULL; arc = next_out_arc (arc))

7051     /* Ignore cyclescontaining one state and `cycle advance' arcs. */

7052     if (arc->to_state != state

7053        &&(arc->insn->insn_reserv_decl

7054            != DECL_INSN_RESERV (advance_cycle_insn_decl)))

7055     {

7056       length = longest_path_length(arc->to_state);

7057       if (length > result)

7058         result = length;

7059     }

7060   state->longest_path_length = result + 1;

7061   returnresult;

7062 }

9.6.4.1.    输出表

正如在绝大多数自动机里,表驱动通常能给出期望的性能,在这里产生的自动机也同样是表驱动的。函数output_tables为这个自动机产生表。

 

8077 static void

8078 output_tables (void)                                                                           ingenautomata.c

8079 {

8080   automaton_tautomaton;

8081

8082 #ifndef NDEBUG

8083   locked_states_num = 0;

8084 #endif

8085   initiate_min_issue_delay_pass_states ();

8086   for(automaton = description->first_automaton;

8087       automaton != NULL;

8088       automaton = automaton->next_automaton)

8089   {

8090     output_translate_vect(automaton);

8091     output_trans_table (automaton);

8092     fprintf (output_file, "\n#if%s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);

8093     output_state_alts_table(automaton);

8094     fprintf (output_file, "\n#endif /* #if%s */\n\n",

8095              AUTOMATON_STATE_ALTS_MACRO_NAME);

8096     output_min_issue_delay_table(automaton);

8097     output_dead_lock_vect(automaton);

8098     fprintf (output_file, "\n#if%s\n\n", CPU_UNITS_QUERY_MACRO_NAME);

8099     output_reserved_units_table(automaton);

8100     fprintf (output_file, "\n#endif /* #if%s */\n\n",

8101              CPU_UNITS_QUERY_MACRO_NAME);

8102   }

8103   fprintf (output_file, "\n#define %s %d\n\n",ADVANCE_CYCLE_VALUE_NAME,

8104         DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);

8105 }

9.6.4.1.1.           输出等效指令集表

在上面的8085行,initiate_min_issue_delay_pass_statescurr_state_pass_num初始化为0。我们已经知道自动机由等效指令类别的指令集,而不是单个指令所驱动。通常,给定某个指令编码(指令的识别符),需要找出所从属的等效类别。在自动机的生成一节,我们已经找出这个关系。这需要一个表来把外部的指令编号映射到内部的指令编号(实际是等效类别的编号)。

 

7439 static void

7440 output_translate_vect (automaton_t automaton)                                     ingenautomata.c

7441 {

7442   ainsn_t ainsn;

7443   int insn_value;

7444   vla_hwint_t translate_vect;

7445

7446   VLA_HWINT_CREATE (translate_vect, 250,"translate vector");

7447   VLA_HWINT_EXPAND (translate_vect, description->insns_num);

7448   for(insn_value = 0; insn_value < description->insns_num; insn_value++)

7449     /* Undefinedvalue */

7450     VLA_HWINT (translate_vect, insn_value) =automaton->insn_equiv_classes_num;

7451   for (ainsn = automaton->ainsn_list; ainsn != NULL;ainsn = ainsn->next_ainsn)

7452    VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)

7453      = ainsn->insn_equiv_class_num;

7454   fprintf (output_file,

7455         "/* Vector translating externalinsn codes to internal ones.*/\n");

7456   fprintf (output_file, "static const ");

7457   output_range_type(output_file,0, automaton->insn_equiv_classes_num);

7458   fprintf (output_file, " ");

7459   output_translate_vect_name(output_file,automaton);

7460   fprintf (output_file, "[] ATTRIBUTE_UNUSED ={\n");

7461   output_vect(VLA_HWINT_BEGIN (translate_vect),

7462                 VLA_HWINT_LENGTH (translate_vect));

7463   fprintf (output_file, "};\n\n");

7464   VLA_HWINT_DELETE (translate_vect);

7465 }

 

我们已经知道自动机的insn_equiv_classes_num记录了在该自动机中的等效类别的数目,而ainsn的域insn_equiv_class_num记录了它所从属的等效类别的编号(参见set_insn_equiv_classes)。

output_range_type确定,在输出文件中,为这个变量所声明的类型。

 

7008 static void

7009 output_range_type (FILE *f, long intmin_range_value,                         ingenautomata.c

7010                 long int max_range_value)

7011 {

7012   if (min_range_value >= 0 &&max_range_value <= 255)

7013     fprintf (f, "unsigned char");

7014   else if (min_range_value >= -127&& max_range_value <= 127)

7015     fprintf (f, "signed char");

7016   else if (min_range_value >= 0 &&max_range_value <= 65535)

7017     fprintf (f, "unsigned short");

7018   else if (min_range_value >= -32767&& max_range_value <= 32767)

7019     fprintf (f, "short");

7020   else

7021     fprintf (f, "int");

7022 }

 

然后,output_translate_vect_name为自动机输出名字,接着在7027行,在create_automataautomaton_order_num被赋值为该序列号。

 

7168 static void

7169 output_translate_vect_name (FILE *f, automaton_t automaton)              ingenautomata.c

7170 {

7171   if(automaton->corresponding_automaton_decl == NULL)

7172     fprintf (f, "translate_%d",automaton->automaton_order_num);

7173   else

7174     fprintf (f, "%s_translate",automaton->corresponding_automaton_decl->name);

7175 }

 

在这一步,为自动机我们输出以下代码。假定该自动机的等效指令类别的数目少于255,并且仅构建了一个自动机(缺省的情形,不过对于现代CPU架构,通常会声明多个自动机)。

 

       /* Vector translating external insn codes to internalones.*/

       static const unsigned char translate_0 []ATTRIBUTE_UNUSED = {

 

在这里vectoutput_translate_vect中的translate_vect,因为所有指令被确信,当构建自动机时,可以被发布,在vect中的每个元素(指令)将包含等效集编号。注意vect使用指令编号——指令的序列号作为索引。

 

7108 static void

7109 output_vect (vect_el_t *vect, intvect_length)                                        ingenautomata.c

7110 {

7111   int els_on_line;

7112

7113   els_on_line = 1;

7114   if (vect_length == 0)

7115     fprintf (output_file,

7116           "0 /* This is dummy el becausethe vect is empty */");

7117   else

7118   {

7119     do

7120     {

7121       fprintf (output_file, "%5ld",(long) *vect);

7122       vect_length--;

7123       if (els_on_line == 10)

7124       {

7125         els_on_line = 0;

7126         fprintf (output_file, ",\n");

7127       }

7128       else if (vect_length != 0)

7129         fprintf (output_file, ", ");

7130       els_on_line++;

7131       vect++;

7132     }

7133     while(vect_length != 0);

7134   }

7135 }

 

因此输出的translate_0是一个外部指令编号与指令单元预订等效类别编号之间的映射。

9.6.4.1.2.           输出状态迁移表

状态,根据其创建的方式,可以显示所占用的资源。状态迁移由指令(实际以等效指令类别)发布所驱动,arc被创建来记录迁移的细节。看到状态与arc是不可分割的数据,输出的表应该体现两者。

 

7731 static void

7732 output_trans_table (automaton_t automaton)                                         ingenautomata.c

7733 {

7734   state_t *state_ptr;

7735   arc_t arc;

7736   vla_hwint_t transition_vect;

7737

7738   undefined_vect_el_value = automaton->achieved_states_num;

7739   automaton->trans_table = create_state_ainsn_table (automaton);

7740   /* Create vect ofpointers to states ordered by num of transitions

7741     from the state (state with the maximum numis the first).  */

7742   VLA_PTR_CREATE (output_states_vect, 1500,"output states vector");

7743   pass_states(automaton, add_states_vect_el);

7744   qsort (VLA_PTR_BEGIN (output_states_vect),

7745        VLA_PTR_LENGTH (output_states_vect),

7746        sizeof (state_t), compare_transition_els_num);

7747   VLA_HWINT_CREATE (transition_vect, 500,"transition vector");

7748   for(state_ptr = VLA_PTR_BEGIN (output_states_vect);

7749       state_ptr <= (state_t*) VLA_PTR_LAST (output_states_vect);

7750       state_ptr++)

7751   {

7752     VLA_HWINT_NULLIFY (transition_vect);

7753     for (arc =first_out_arc (*state_ptr);

7754         arc != NULL;

7755         arc = next_out_arc (arc))

7756     {

7757       if (arc->insn == NULL)

7758         abort ();

7759       if(arc->insn->first_ainsn_with_given_equialence_num)

7760         add_vect_el(&transition_vect, arc->insn,

7761                   arc->to_state->order_state_num);

7762     }

7763     add_vect(automaton->trans_table, (*state_ptr)->order_state_num,

7764              VLA_HWINT_BEGIN (transition_vect),

7765              VLA_HWINT_LENGTH(transition_vect));

7766   }

7767   output_state_ainsn_table

7768     (automaton->trans_table, (char *)"state transitions",

7769      output_trans_full_vect_name, output_trans_comb_vect_name,

7770      output_trans_check_vect_name, output_trans_base_vect_name);

7771   VLA_PTR_DELETE (output_states_vect);

7772   VLA_HWINT_DELETE (transition_vect);

7773 }

 

在7738行的achieved_states_num记录了该自动机的状态的数目(参见enumerate_states)。在7739行的create_state_ainsn_table构建了state_ainsn_table的一个实例。

 

7481 static state_ainsn_table_t

7482 create_state_ainsn_table (automaton_t automaton)                                 ingenautomata.c

7483 {

7484   state_ainsn_table_ttab;

7485   int full_vect_length;

7486   int i;

7487

7488   tab = create_node (sizeof(struct state_ainsn_table));

7489   tab->automaton = automaton;

7490   VLA_HWINT_CREATE (tab->comb_vect, 10000,"comb vector");

7491   VLA_HWINT_CREATE (tab->check_vect, 10000,"check vector");

7492   VLA_HWINT_CREATE (tab->base_vect, 1000,"base vector");

7493   VLA_HWINT_EXPAND (tab->base_vect,automaton->achieved_states_num);

7494   VLA_HWINT_CREATE (tab->full_vect, 10000,"full vector");

7495   full_vect_length =(automaton->insn_equiv_classes_num

7496                   *automaton->achieved_states_num);

7497   VLA_HWINT_EXPAND (tab->full_vect,full_vect_length);

7498   for (i = 0; i< full_vect_length; i++)

7499     VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;

7500   tab->min_base_vect_el_value= 0;

7501  tab->max_base_vect_el_value = 0;

7502   tab->min_comb_vect_el_value = 0;

7503   tab->max_comb_vect_el_value = 0;

7504   return tab;

7505 }

 

state_ainsn_table具有如下定义。它为输出表收集数据。

 

1280 struct state_ainsn_table                                                                        ingenautomata.c

1281 {

1282   /* Automaton towhich given table belongs.  */

1283   automaton_tautomaton;

1284   /* The followingtree vectors for comb vector implementation of the

1285      table. */

1286  vla_hwint_t comb_vect;

1287   vla_hwint_tcheck_vect;

1288  vla_hwint_t base_vect;

1289   /* This is simpleimplementation of the table.  */

1290  vla_hwint_t full_vect;

1291   /* Minimal andmaximal values of the previous vectors. */

1292   int min_comb_vect_el_value,max_comb_vect_el_value;

1293   int min_base_vect_el_value,max_base_vect_el_value;

1294 };

 

207  typedef struct state_ainsn_table*state_ainsn_table_t;                               ingenautomata.c

 

create_state_ainsn_table的7743行,add_states_vect_elpass_states把该自动机的每个状态加入类型为vla_ptr_toutput_states_vect中。

 

7723 static void

7724 add_states_vect_el (state_tstate)                                                          ingenautomata.c

7725 {

7726   VLA_PTR_ADD (output_states_vect, state);

7727 }

 

output_trans_table的7746行,compare_transition_els_num根据迁移的数目,以升序排序。然后output_trans_table遍历output_states_vect中,现在以迁移编号的升序排序的状态。对于每个来自该状态的迁移,正如我们已经知道的,由特定的指令所触发,并且所有的指令通过其所预订的资源来分组(等效类别)。在7759行的first_ainsn_with_given_equialence_num为在该类别中首先找到的指令所设置(参见set_insn_equiv_classes)。对于这个类别的指令,目的状态的序列号(参见在7761行的order_state_num,在下面通过el_value传递),以及该指令(参见下面的ainsn)被传递给add_vect_el

 

7702 static void

7703 add_vect_el (vla_hwint_t *vect, ainsn_tainsn, int el_value)                    ingenautomata.c

7704 {

7705   int equiv_class_num;

7706   int vect_index;

7707

7708   if (ainsn == NULL)

7709     abort ();

7710   equiv_class_num = ainsn->insn_equiv_class_num;

7711   for(vect_index = VLA_HWINT_LENGTH (*vect);

7712       vect_index <= equiv_class_num;

7713       vect_index++)

7714     VLA_HWINT_ADD (*vect, undefined_vect_el_value);

7715   VLA_HWINT (*vect, equiv_class_num) =el_value;

7716 }

 

看到add_vect_el位于FOR循环之内,因而,transition_vect被输入如下数据。注意到order_state_num是目的状态的序列号,并且其位置由触发该迁移的等效指令类别编号所决定。因此这个数组把所有目的状态与给定源状态的触发指令绑定起来。

由于VLA_HWINT_ADD的作用是把vect扩大一个单元,然后在vect的末尾加入undefined_vect_el_value,因此vect的大小是最大的“equiv_class_num”。

图97:输出state_transition表,步骤1

接着这个数组由下面的vect传递给add_vect。而参数tab指向在create_state_ainsn_table中构建的trans_table,它现在还是空的。

 

7566 static void

7567 add_vect (state_ainsn_table_ttab, int vect_num,                                           ingenautomata.c

7568         vect_el_t *vect, int vect_length)

7569 {

7570   int real_vect_length;

7571   vect_el_t *comb_vect_start;

7572   vect_el_t *check_vect_start;

7573   int comb_vect_index;

7574   int comb_vect_els_num;

7575   int vect_index;

7576   int first_unempty_vect_index;

7577   int additional_els_num;

7578   int no_state_value;

7579  vect_el_t vect_el;

7580   int i;

7581

7582   if (vect_length == 0)

7583     abort ();

7584   real_vect_length =tab->automaton->insn_equiv_classes_num;

7585   if (vect [vect_length - 1] == undefined_vect_el_value)

7586     abort ();

7587  /* Form full vectorin the table: */

7588   for (i = 0; i< vect_length; i++)

7589     VLA_HWINT (tab->full_vect,

7590                  i +tab->automaton->insn_equiv_classes_num * vect_num)

7591       = vect [i];

7592   /* Form comb vectorin the table: */

7593   if (VLA_HWINT_LENGTH (tab->comb_vect) !=VLA_HWINT_LENGTH (tab->check_vect))

7594     abort ();

7595   comb_vect_start = VLA_HWINT_BEGIN(tab->comb_vect);

7596   comb_vect_els_num = VLA_HWINT_LENGTH(tab->comb_vect);

7597   for(first_unempty_vect_index = 0;

7598       first_unempty_vect_index <vect_length;

7599       first_unempty_vect_index++)

7600     if (vect [first_unempty_vect_index] != undefined_vect_el_value)

7601       break;

7602   /* Search for theplace in comb vect for the inserted vect. */

7603   for(comb_vect_index = 0;

7604       comb_vect_index < comb_vect_els_num;

7605       comb_vect_index++)

7606   {

7607     for(vect_index = first_unempty_vect_index;

7608         vect_index < vect_length

7609           && vect_index +comb_vect_index < comb_vect_els_num;

7610         vect_index++)

7611       if (vect [vect_index] != undefined_vect_el_value

7612          && (comb_vect_start[vect_index + comb_vect_index]

7613                != undefined_vect_el_value))

7614         break;

7615       if (vect_index >= vect_length

7616          || vect_index + comb_vect_index >=comb_vect_els_num)

7617         break;

7618   }

7619   /* Slot wasfound.  */

7620   additional_els_num = comb_vect_index +real_vect_length - comb_vect_els_num;

7621   if (additional_els_num < 0)

7622     additional_els_num = 0;

7623  /* Expand comb andcheck vectors.  */

7624  vect_el = undefined_vect_el_value;

7625   no_state_value =tab->automaton->achieved_states_num;

7626   while(additional_els_num > 0)

7627   {

7628     VLA_HWINT_ADD (tab->comb_vect, vect_el);

7629     VLA_HWINT_ADD (tab->check_vect,no_state_value);

7630     additional_els_num--;

7631   }

7632   comb_vect_start = VLA_HWINT_BEGIN(tab->comb_vect);

7633   check_vect_start = VLA_HWINT_BEGIN(tab->check_vect);

7634   if (VLA_HWINT_LENGTH (tab->comb_vect)

7635      < (size_t) (comb_vect_index +real_vect_length))

7636     abort ();

7637  /* Fill comb andcheck vectors.  */

7638   for(vect_index = 0; vect_index < vect_length; vect_index++)

7639     if (vect [vect_index] != undefined_vect_el_value)

7640     {

7641       if (comb_vect_start [comb_vect_index +vect_index]

7642           != undefined_vect_el_value)

7643         abort ();

7644       comb_vect_start [comb_vect_index +vect_index] = vect [vect_index];

7645       if (vect [vect_index] < 0)

7646         abort ();

7647       if(tab->max_comb_vect_el_value < vect [vect_index])

7648         tab->max_comb_vect_el_value = vect[vect_index];

7649       if (tab->min_comb_vect_el_value >vect [vect_index])

7650         tab->min_comb_vect_el_value = vect[vect_index];

7651       check_vect_start [comb_vect_index +vect_index] = vect_num;

7652     }

7653   if (tab->max_comb_vect_el_value < undefined_vect_el_value)

7654     tab->max_comb_vect_el_value = undefined_vect_el_value;

7655   if (tab->min_comb_vect_el_value > undefined_vect_el_value)

7656     tab->min_comb_vect_el_value = undefined_vect_el_value;

7657   if (tab->max_base_vect_el_value <comb_vect_index)

7658     tab->max_base_vect_el_value =comb_vect_index;

7659   if (tab->min_base_vect_el_value >comb_vect_index)

7660     tab->min_base_vect_el_value =comb_vect_index;

7661   VLA_HWINT (tab->base_vect, vect_num) =comb_vect_index;

7662 }

 

在7588行的FOR循环里,tab(类型为state_ainsn_table)的full_vect实际上可视为一个二维数组,它的内容如下图所示。


图98:输出state_transition表,步骤2

看到这个数组很可能是稀疏。为了减小状态相关函数输出的大小,我们可以构建一个类似但更加紧凑的vector,tabcomb_vect就是这样的一个vector。因为这个vector不是与状态一一对应的,我们需要额外的vector来保存源状态的信息。

为了更好地理解comb_vectcheck_vect的填充过程,我们假定这个自动机总共具有8个有效状态,在第一个状态中,可以迁移到状态3及5(这里我们不需要在意状态的编号),第二个状态的目的状态的编号分别是2及4,而第三个状态,则是编号为3及6的状态。

在7597行的FOR循环首先找出图97所示数组中第一个有效填充单元的索引,该索引将是7607行FOR循环的初始值。而7603行的FOR循环扫描comb_vectvect,满足7611行条件,表示comb_vect对应的单元已经进行了有效填充。

对于第一个状态,起初comb_vect是空的,因此7620行的additional_els_num将是automaton->insn_equiv_classes_num。在7626行的WHILE循环,把comb_vect填充为全undefined_vect_el_value,而check_vect为全automaton->achieved_states_num(自动机状态数目)。在接下来7638行的FOR循环中,填充comb_vect与第一个状态的数组相同,check_vect的对应位置为源状态编号,如下图所示。

图99:输出state_transition表,步骤3

然后对于第二个状态,transition_vect重新填充(output_trans_table的7752行),在7603行的FOR循环检查comb_vect是否在对应的位置已经填充了,若然在7614行跳出7607行的FOR循环,在7603行递增comb_vect_index重新尝试,直到某个comb_vect_index能使comb_vect容纳transition_vect。对于第二个状态,显然comb_vect_index为0就可以了,如下图所示。

图100:输出state_transition表,步骤4

对于第三个状态,comb_vect [2]已经为状态1所占据,因此递增 comb_vect_index为1,但此时comb_vect [3]也已经为状态2使用,继续递增 comb_vect_index到2,可是comb_vect [4]也已被状态1使用。直到递增 comb_vect_index到3,此时comb_vect [5]可用,加入状态3的信息后,得到如下图。

图101:输出state_transition表,步骤5

在上图中,我们忽略了向量base_vect,它以源状态序号为索引,并且其内容为comb_vect_index。从这个索引,我们可以恢复状态的初始的vector。

现在是时候由output_state_ainsn_table输出我们在上面看到的这些vector了。

 

7509 static void

7510 output_state_ainsn_table (state_ainsn_table_t tab, char *table_name,        ingenautomata.c

7511                        void (*output_full_vect_name_func) (FILE *,automaton_t),

7512                        void (*output_comb_vect_name_func) (FILE *,automaton_t),

7513                        void (*output_check_vect_name_func) (FILE *,automaton_t),

7514                        void (*output_base_vect_name_func) (FILE *,automaton_t))

7515 {

7516   if (!comb_vect_p (tab))

7517   {

7518     fprintf (output_file, "/* Vector for%s.  */\n", table_name);

7519     fprintf (output_file, "static const");

7520     output_range_type(output_file,tab->min_comb_vect_el_value,

7521                    tab->max_comb_vect_el_value);

7522     fprintf (output_file, " ");

7523     (*output_full_vect_name_func) (output_file,tab->automaton);

7524     fprintf (output_file, "[]ATTRIBUTE_UNUSED = {\n");

7525     output_vect(VLA_HWINT_BEGIN (tab->full_vect),

7526                VLA_HWINT_LENGTH(tab->full_vect));

7527     fprintf (output_file, "};\n\n");

7528   }

7529   else

7530   {

7531     fprintf (output_file, "/* Comb vectorfor %s.  */\n", table_name);

7532     fprintf (output_file, "static const");

7533     output_range_type(output_file,tab->min_comb_vect_el_value,

7534                     tab->max_comb_vect_el_value);

7535     fprintf (output_file, " ");

7536     (*output_comb_vect_name_func) (output_file,tab->automaton);

7537     fprintf (output_file, "[]ATTRIBUTE_UNUSED = {\n");

7538     output_vect (VLA_HWINT_BEGIN(tab->comb_vect),

7539                VLA_HWINT_LENGTH(tab->comb_vect));

7540     fprintf (output_file, "};\n\n");

7541     fprintf (output_file, "/* Check vectorfor %s.  */\n", table_name);

7542     fprintf (output_file, "static const");

7543     output_range_type(output_file,0, tab->automaton->achieved_states_num);

7544     fprintf (output_file, " ");

7545     (*output_check_vect_name_func) (output_file,tab->automaton);

7546     fprintf (output_file, "[] = {\n");

7547     output_vect(VLA_HWINT_BEGIN (tab->check_vect),

7548                VLA_HWINT_LENGTH(tab->check_vect));

7549     fprintf (output_file, "};\n\n");

7550     fprintf (output_file, "/* Base vectorfor %s.  */\n", table_name);

7551     fprintf (output_file, "static const");

7552     output_range_type(output_file,tab->min_base_vect_el_value,

7553                     tab->max_base_vect_el_value);

7554     fprintf (output_file, " ");

7555     (*output_base_vect_name_func) (output_file,tab->automaton);

7556     fprintf (output_file, "[] = {\n");

7557     output_vect(VLA_HWINT_BEGIN (tab->base_vect),

7558                VLA_HWINT_LENGTH(tab->base_vect));

7559     fprintf (output_file, "};\n\n");

7560   }

7561 }

 

上面在7516行,comb_vect_p检查comb_vect是否大于full_vect的五分之二。若然,我们使用comb_vect,否则使用full_vect。假定我们使用comb_vect,现在我们将得到如下输出文件(insn-attrtab.c)。

 

/*Vector translating external insn codes to internal ones.*/

       static const unsigned char translate_0 []ATTRIBUTE_UNUSED = {

         `equivalent class set`  //in description order

       };

 

/*Comb vector for state transitions */

staticconst unsigned char transitions_0 [] ATTRIBUTE_UNUSED = {

  `content of comb_vect`              // refer to add_vect

};

 

/*Check vector for state transitions */

staticconst unsigned char check_0 [] ATTRIBUTE_UNUSED = {

  `content of check_vect`              // refer to add_vect

};

 

/* Basevector for state transitions */

staticconst unsigned char base_0 [] ATTRIBUTE_UNUSED = {

  `content of base_vect`  // refer to add_vect

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值