GCC后端及汇编发布(27-续)
2011-06-11 17:14
323 查看
build_automaton (continued)
6418
if (progress_flag
)
6419
fprintf (stderr
, " done/n");
6420
ticker_off (&NDFA_time
);
6421
count_states_and_arcs
(automaton, &states_num, &arcs_num);
6422
automaton->NDFA_states_num = states_num;
6423
automaton->NDFA_arcs_num = arcs_num;
6424
ticker_on (&NDFA_to_DFA_time
);
6425
if (progress_flag
)
6426
{
6427
if (automaton->corresponding_automaton_decl
== NULL)
6428
fprintf (stderr
, "Make anonymous
DFA");
6429
else
6430
fprintf (stderr
, "Make DFA `%s'",
6431
automaton->corresponding_automaton_decl->name);
6432
fprintf (stderr
, " (1 dot is 100 new
states):");
6433
}
count_states_and_arcs
计算指定自动机的状态及迁移的数目。
6387
static
void
6388
count_states_and_arcs
(automaton_t
automaton, int *states_num,
in genautomata.c
6389
int *arcs_num)
6390
{
6391
curr_counted_states_num
= 0;
6392
curr_counted_arcs_num
= 0;
6393
pass_states
(automaton, incr_states_and_arcs_nums
);
6394
*states_num = curr_counted_states_num
;
6395
*arcs_num = curr_counted_arcs_num
;
6396
}
5978
static
void
5979
pass_states
(automaton_t
automaton, void (*applied_func) (state_t
state)) in genautomata.c
5980
{
5981
curr_state_graph_pass_num
++;
5982
pass_state_graph
(automaton->start_state, applied_func
);
5983
}
上面在
6394
行,
curr_state_graph_pass_num
确保每个状态将仅会被计算一次。在下面的
5966
行我们可以看到这一点。
5961
static
void
5962
pass_state_graph
(state_t
start_state, void (*applied_func) (state_t
state))
in genautomata.c
5963
{
5964
arc_t arc;
5965
5966
if (start_state->pass_num == curr_state_graph_pass_num
)
5967
return
;
5968
start_state->pass_num = curr_state_graph_pass_num
;
5969
(*applied_func
)
(start_state);
5970
for
(arc = first_out_arc
(start_state);
5971
arc != NULL;
5972
arc = next_out_arc (arc))
5973
pass_state_graph
(arc->to_state, applied_func);
5974
}
对于每个状态,调用
incr_states_and_arcs_nums
。
6376
static
void
6377
incr_states_and_arcs_nums
(state_t
state)
in
genautomata.c
6378
{
6379
arc_t arc;
6380
6381
curr_counted_states_num
++;
6382
for
(arc = first_out_arc
(state); arc != NULL; arc = next_out_arc (arc))
6383
curr_counted_arcs_num
++;
6384
}
现在是时候把
NDFA
转换为
DFA
了。继续看
build_automaton
。
build_automaton (continued)
6434
NDFA_to_DFA
(automaton);
6435
if (progress_flag
)
6436
fprintf (stderr
, " done/n");
6437
ticker_off (&NDFA_to_DFA_time
);
6438
count_states_and_arcs
(automaton, &states_num, &arcs_num);
6439
automaton->DFA_states_num = states_num;
6440
automaton->DFA_arcs_num = arcs_num;
6441
if (!no_minimization_flag
)
6442
{
6443
ticker_on (&minimize_time
);
6444
if (progress_flag
)
6445
{
6446
if
(automaton->corresponding_automaton_decl == NULL)
6447
fprintf (stderr, "Minimize
anonymous DFA...");
6448
else
6449
fprintf (stderr
,
"Minimize DFA `%s'...",
6450
automaton->corresponding_automaton_decl->name);
6451
}
6452
minimize_DFA
(automaton);
6453
if (progress_flag
)
6454
fprintf (stderr
, "done/n");
6455
ticker_off (&minimize_time
);
6456
count_states_and_arcs
(automaton, &states_num, &arcs_num);
6457
automaton->minimal_DFA_states_num =
states_num;
6458
automaton->minimal_DFA_arcs_num =
arcs_num;
6459
}
6460
}
在这里转换
NDFA
到
DFA
的算法很简单。对于我们的例子,从
start_state
状态出发,可以迁移到
SA
,
SB
或
SC
状态。为了解决这个非确定性,我们构建了一个新状态
A’
,
A’ = {SA
∪
SB
∪
SC} –
这意味着它是一个在状态
S
下由类别为
(A|B|C)
的指令所触发的组合状态,它具有所有从状态
SA
,
SB
及
SC
出发的迁移。看到这个从状态
S
到
A’
的迁移,现在是确定性的。对所有具有非确定性迁移的状态重复上述步骤,直到不存在这样的状态。
为了更好地清楚这个算法,考虑以下自动机。
图
74
:
NDFA
转换到
DFA
的例子,步骤
1
除了状态
S
以外,从每个状态出发,可以找到至少一个闭环
–
对于可行的芯片这是个必须条件,因为任意开放的节点意味着芯片将死在那一点上。并且注意到初始状态(
S
)不能有进入的迁移。这个自动机例子是一个
NDFA
,看到从状态
S
到状态
A1
的迁移是非确定性的。
图
75
:
NDFA
转换到
DFA
的例子,步骤
2
在状态
A1
及
A2
上应用这个算法,我们可以得到上图。状态
A12
仍然是非确定性的,因为指令类别
ib
可以触发两个迁移。看到状态
A12
是从状态
A1
及
A2
构建的复合状态,现在我们不能确定其单元预订了。不过,我们不再需要单元预订,我们所需要的仅是状态及其之间的迁移。
图
76
:
NDFA
转换到
DFA
的例子,步骤
3
又,合并状态
B1
及
B2
,我们得到上图,不过这个状态仍然是非确定性的,因为
advance_cycle_insn_decl
将触发两个状态迁移。看到这个状态
B12
甚至不能在前面自动机生成过程中存在。
图
77
:
NDFA
转换到
DFA
的例子,步骤
4
最后修改出的确定性自动机显示于上图。注意到这个确定性版本及非确定性版本,仅从指令发布机会的意义上而言,是相等的。
5917
static
void
5918
NDFA_to_DFA
(automaton_t
automaton)
5919
{
5920
state_t
start_state;
5921
state_t
state;
5922
decl_t
decl;
5923
vla_ptr_t state_stack;
5924
int i;
5925
int states_n;
5926
5927
VLA_PTR_CREATE (state_stack, 150, "state
stack");
5928
/* Create the start
state (empty state).
*/
5929
start_state = automaton->start_state;
5930
start_state->it_was_placed_in_stack_for_DFA_forming
= 1;
5931
VLA_PTR_ADD (state_stack, start_state);
5932
states_n = 1;
5933
while
(VLA_PTR_LENGTH (state_stack) != 0)
5934
{
5935
state = VLA_PTR (state_stack,
VLA_PTR_LENGTH (state_stack) - 1);
5936
VLA_PTR_SHORTEN (state_stack, 1);
5937
form_arcs_marked_by_insn
(state);
5938
for
(i = 0; i < description
->decls_num;
i++)
5939
{
5940
decl = description
->decls [i];
5941
if (decl->mode == dm_insn_reserv
5942
&& create_composed_state
5943
(state, DECL_INSN_RESERV
(decl)->arcs_marked_by_insn,
5944
&state_stack))
5945
{
5946
states_n++;
5947
if (progress_flag
&& states_n % 100 == 0)
5948
fprintf (stderr
, ".");
5949
}
5950
}
5951
}
5952
VLA_PTR_DELETE (state_stack);
5953
}
记住对于非确定性自动机,在我们上面的例子中,将评估
define_insn_reservation
中的每个替代;而对于确定性自动机,将仅评估第一个合格的替代。从这之后,这将形成很大的区别。事实上,当替代以确定性方式来处理时,构建出的自动机已经就是确定性的。
5787
static
void
5788
form_arcs_marked_by_insn
(state_t
state)
in
genautomata.c
5789
{
5790
decl_t
decl;
5791
arc_t arc;
5792
int i;
5793
5794
for
(i = 0; i < description
->decls_num; i++)
5795
{
5796
decl = description
->decls [i];
5797
if (decl->mode == dm_insn_reserv)
5798
DECL_INSN_RESERV (decl)->arcs_marked_by_insn
= NULL;
5799
}
5800
for
(arc =
first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5801
{
5802
if (arc->insn == NULL)
5803
abort ();
5804
arc->next_arc_marked_by_insn
5805
= arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5806
arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5807
}
5808
}
在跨越发布包含替代的指令类别的状态中,为了把这些特殊的迁移与其它确定性迁移区分开来,
form_arcs_marked_by_insn
将通过
next_arc_marked_by_insn
域链接这些迁移(以
arc
的形式)。
在非确定性的例子中,对于
start_state
将得到如下。
对于指令类别(
E|F
)
arcSF->next_arc_marked_by_insn = NULL (arcSF->to_state =
stateSF)
arcSF->insn->insn_reserv_decl->arcs_marked_by_insn = arcSF
arcSE->next_arc_marked_by_insn = arcSF (arcSE->to_state =
stateSE)
arcSE->insn->insn_reserv_decl->arcs_marked_by_insn = arcSE
(最后的值)
对于指令类别(
A|B|C
)
arcSC->next_arc_marked_by_insn = NULL (arcSC->to_state =
stateSC)
arcSC->insn->insn_reserv_decl->arcs_marked_by_insn = arcSC
arcSB->next_arc_marked_by_insn = arcSC (arcSB->to_state = stateSB)
arcSB->insn->insn_reserv_decl->arcs_marked_by_insn = arcSB
arcSA->next_arc_marked_by_insn = arcSB (arcSA->to_state =
stateSA)
arcSA->insn->insn_reserv_decl->arcs_marked_by_insn = arcSA
(最后的值)
(注意到上面的两部分被
state
的
arc
的
next_out_arc
域链接起来)
在确定性的例子中,对于
start_state
将得到如下。
对于指令类别
A
arcSA->next_arc_marked_by_insn = NULL (arcSA->to_state =
stateSA)
arcSA->insn->insn_reserv_decl->arcs_marked_by_insn = arcSA
对于指令类别
E
arcSE->next_arc_marked_by_insn = NULL (arcSE->to_state =
stateSE)
arcSE->insn->insn_reserv_decl->arcs_marked_by_insn = arcSE
(注意到上面的两部分被
state
的
arc
的
next_out_arc
域链接起来)
显示在下图,
insn (x1|x2|x3)
代表在
define_insn_reservation
中具有三个替代:
x1
,
x2
及
x3
的指令类别。在图中两个
arcs_marked_by_insn
是对应不同
insn_reserv_decl
的域
–
对应
define_insn_reservations
模式的
decl
。
图
78
:
构建
DFA
,阶段
2
现在在
state_stack
里仅是
state_start
。对于确定性自动机,
create_composed_state
是简单的,因为
next_arc_marked_by_insn
总是
NULL
(参见
5853
行的检查)。它将把在
5382
行获取的
to_state
压入
state_stack
并返回。现在在
state_stack
里,是
SA
,
SE
。
在非确定性自动机的例子中,域
component_states
用于所谓的复合状态(例如,上图中的状态
A12
,
B12
,
xy
)。对于具有替代
A
,
B
,
C
的指令类别来说,第一个参数
original_state
是
start_state
,而第二个参数
arcs_marked_by_insn
指向上图中的
arcs_marked_by_insn
,它是
insn_reserv_decl – define_insn_reservation
模式的
decl
,中的域。
5814
static
int
5815
create_composed_state
(state_t
original_state, arc_t arcs_marked_by_insn,
in
genautomata.c
5816
vla_ptr_t *state_stack)
5817
{
5818
state_t
state;
5819
alt_state_t alt_state, curr_alt_state;
5820
alt_state_t new_alt_state;
5821
arc_t curr_arc;
5822
arc_t next_arc;
5823
state_t
state_in_table;
5824
state_t
temp_state;
5825
alt_state_t canonical_alt_states_list;
5826
int alts_number;
5827
int new_state_p = 0;
5828
5829
if (arcs_marked_by_insn == NULL)
5830
return
new_state_p;
5831
if
(arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5832
state = arcs_marked_by_insn->to_state;
5833
else
5834
{
5835
if (!ndfa_flag
)
5836
abort ();
5837
/* Create
composed state.
*/
5838
state = get_free_state (0,
arcs_marked_by_insn->to_state->automaton);
5839
curr_alt_state = NULL;
5840
for
(curr_arc = arcs_marked_by_insn;
5841
curr_arc != NULL;
5842
curr_arc =
curr_arc->next_arc_marked_by_insn)
5843
if
(curr_arc->to_state->component_states == NULL)
5844
{
5845
new_alt_state = get_free_alt_state ();
5846
new_alt_state->next_alt_state =
curr_alt_state;
5847
new_alt_state->state =
curr_arc->to_state;
5848
curr_alt_state = new_alt_state;
5849
}
5850
else
5851
for
(alt_state = curr_arc->to_state->component_states;
5852
alt_state != NULL;
5853
alt_state =
alt_state->next_sorted_alt_state)
5854
{
5855
new_alt_state = get_free_alt_state
();
5856
new_alt_state->next_alt_state =
curr_alt_state;
5857
new_alt_state->state =
alt_state->state;
5858
if
(alt_state->state->component_states != NULL)
5859
abort ();
5860
curr_alt_state = new_alt_state;
5861
}
5862
/* There are
not identical sets in the alt state list.
*/
5863
canonical_alt_states_list = uniq_sort_alt_states
(curr_alt_state);
5864
if
(canonical_alt_states_list->next_sorted_alt_state == NULL)
5865
{
5866
temp_state = state;
5867
state =
canonical_alt_states_list->state;
5868
free_state (temp_state);
5869
}
5870
else
5871
{
5872
state->component_states =
canonical_alt_states_list;
5873
state_in_table = insert_state (state);
5874
if (state_in_table != state)
5875
{
5876
if
(!state_in_table->it_was_placed_in_stack_for_DFA_forming)
5877
abort ();
5878
free_state (state);
5879
state = state_in_table;
5880
}
5881
else
5882
{
5883
if
(state->it_was_placed_in_stack_for_DFA_forming)
5884
abort ();
5885
new_state_p = 1;
5886
for
(curr_alt_state = state->component_states;
5887
curr_alt_state != NULL;
5888
curr_alt_state =
curr_alt_state->next_sorted_alt_state)
5889
for
(curr_arc = first_out_arc (curr_alt_state->state);
5890
curr_arc != NULL;
5891
curr_arc = next_out_arc (curr_arc))
5892
add_arc
(state, curr_arc->to_state, curr_arc->insn, 1);
5893
}
5894
arcs_marked_by_insn->to_state =
state;
5895
for
(alts_number = 0,
5896
curr_arc =
arcs_marked_by_insn->next_arc_marked_by_insn;
5897
curr_arc != NULL;
5898
curr_arc = next_arc)
5899
{
5900
next_arc =
curr_arc->next_arc_marked_by_insn;
5901
remove_arc (original_state,
curr_arc);
5902
alts_number++;
5903
}
5904
arcs_marked_by_insn->state_alts =
alts_number;
5905
}
5906
}
5907
if
(!state->it_was_placed_in_stack_for_DFA_forming)
5908
{
5909
state->it_was_placed_in_stack_for_DFA_forming
= 1;
5910
VLA_PTR_ADD (*state_stack, state);
5911
}
5912
return
new_state_p;
5913
}
在我们例子中,
curr_alt_state
是一个链表,形如:
curr_alt_state(SA)->next_alt_state(SB)->
next_alt_state(SC)
。然后这个链表被传递给
uniq_sort_alt_states
,这个函数排序
alt_states_list
,并从这个链表中移去重复的
alt_state
。在这里,对于我们的非确定性例子,这个链表没有改变。
在
5864
行,如果
next_sorted_alt_state
不是
NULL
,那么在
5872
行的
state
是新构建的,它必然不出现在
state_table
里,因此我们进入
5882
行。在
create_composed_state
中构建的数据显示如下图。
图
79
:
构建
DFA
,阶段
3
正如我们之前提及的,一旦构建了新状态,当前状态的所有替代的迁移目标,就被设置为这个新状态的迁移目标。然后当前状态,在理论上,可以确定性地迁移到这个新状态,注意到在图中
arcSA
被留下了,蓝色的域被修改了;而其它用于当前状态替代的
arc
都被移除了。接着,这个新状态将被压入
state_stack
。然后在这个状态上重复上面的步骤。直到
state_stack
中没有状态(即,没有状态具有非确定性迁移),
NDFA_to_DFA
才退出。
6418
if (progress_flag
)
6419
fprintf (stderr
, " done/n");
6420
ticker_off (&NDFA_time
);
6421
count_states_and_arcs
(automaton, &states_num, &arcs_num);
6422
automaton->NDFA_states_num = states_num;
6423
automaton->NDFA_arcs_num = arcs_num;
6424
ticker_on (&NDFA_to_DFA_time
);
6425
if (progress_flag
)
6426
{
6427
if (automaton->corresponding_automaton_decl
== NULL)
6428
fprintf (stderr
, "Make anonymous
DFA");
6429
else
6430
fprintf (stderr
, "Make DFA `%s'",
6431
automaton->corresponding_automaton_decl->name);
6432
fprintf (stderr
, " (1 dot is 100 new
states):");
6433
}
count_states_and_arcs
计算指定自动机的状态及迁移的数目。
6387
static
void
6388
count_states_and_arcs
(automaton_t
automaton, int *states_num,
in genautomata.c
6389
int *arcs_num)
6390
{
6391
curr_counted_states_num
= 0;
6392
curr_counted_arcs_num
= 0;
6393
pass_states
(automaton, incr_states_and_arcs_nums
);
6394
*states_num = curr_counted_states_num
;
6395
*arcs_num = curr_counted_arcs_num
;
6396
}
5978
static
void
5979
pass_states
(automaton_t
automaton, void (*applied_func) (state_t
state)) in genautomata.c
5980
{
5981
curr_state_graph_pass_num
++;
5982
pass_state_graph
(automaton->start_state, applied_func
);
5983
}
上面在
6394
行,
curr_state_graph_pass_num
确保每个状态将仅会被计算一次。在下面的
5966
行我们可以看到这一点。
5961
static
void
5962
pass_state_graph
(state_t
start_state, void (*applied_func) (state_t
state))
in genautomata.c
5963
{
5964
arc_t arc;
5965
5966
if (start_state->pass_num == curr_state_graph_pass_num
)
5967
return
;
5968
start_state->pass_num = curr_state_graph_pass_num
;
5969
(*applied_func
)
(start_state);
5970
for
(arc = first_out_arc
(start_state);
5971
arc != NULL;
5972
arc = next_out_arc (arc))
5973
pass_state_graph
(arc->to_state, applied_func);
5974
}
对于每个状态,调用
incr_states_and_arcs_nums
。
6376
static
void
6377
incr_states_and_arcs_nums
(state_t
state)
in
genautomata.c
6378
{
6379
arc_t arc;
6380
6381
curr_counted_states_num
++;
6382
for
(arc = first_out_arc
(state); arc != NULL; arc = next_out_arc (arc))
6383
curr_counted_arcs_num
++;
6384
}
现在是时候把
NDFA
转换为
DFA
了。继续看
build_automaton
。
build_automaton (continued)
6434
NDFA_to_DFA
(automaton);
6435
if (progress_flag
)
6436
fprintf (stderr
, " done/n");
6437
ticker_off (&NDFA_to_DFA_time
);
6438
count_states_and_arcs
(automaton, &states_num, &arcs_num);
6439
automaton->DFA_states_num = states_num;
6440
automaton->DFA_arcs_num = arcs_num;
6441
if (!no_minimization_flag
)
6442
{
6443
ticker_on (&minimize_time
);
6444
if (progress_flag
)
6445
{
6446
if
(automaton->corresponding_automaton_decl == NULL)
6447
fprintf (stderr, "Minimize
anonymous DFA...");
6448
else
6449
fprintf (stderr
,
"Minimize DFA `%s'...",
6450
automaton->corresponding_automaton_decl->name);
6451
}
6452
minimize_DFA
(automaton);
6453
if (progress_flag
)
6454
fprintf (stderr
, "done/n");
6455
ticker_off (&minimize_time
);
6456
count_states_and_arcs
(automaton, &states_num, &arcs_num);
6457
automaton->minimal_DFA_states_num =
states_num;
6458
automaton->minimal_DFA_arcs_num =
arcs_num;
6459
}
6460
}
在这里转换
NDFA
到
DFA
的算法很简单。对于我们的例子,从
start_state
状态出发,可以迁移到
SA
,
SB
或
SC
状态。为了解决这个非确定性,我们构建了一个新状态
A’
,
A’ = {SA
∪
SB
∪
SC} –
这意味着它是一个在状态
S
下由类别为
(A|B|C)
的指令所触发的组合状态,它具有所有从状态
SA
,
SB
及
SC
出发的迁移。看到这个从状态
S
到
A’
的迁移,现在是确定性的。对所有具有非确定性迁移的状态重复上述步骤,直到不存在这样的状态。
为了更好地清楚这个算法,考虑以下自动机。
图
74
:
NDFA
转换到
DFA
的例子,步骤
1
除了状态
S
以外,从每个状态出发,可以找到至少一个闭环
–
对于可行的芯片这是个必须条件,因为任意开放的节点意味着芯片将死在那一点上。并且注意到初始状态(
S
)不能有进入的迁移。这个自动机例子是一个
NDFA
,看到从状态
S
到状态
A1
的迁移是非确定性的。
图
75
:
NDFA
转换到
DFA
的例子,步骤
2
在状态
A1
及
A2
上应用这个算法,我们可以得到上图。状态
A12
仍然是非确定性的,因为指令类别
ib
可以触发两个迁移。看到状态
A12
是从状态
A1
及
A2
构建的复合状态,现在我们不能确定其单元预订了。不过,我们不再需要单元预订,我们所需要的仅是状态及其之间的迁移。
图
76
:
NDFA
转换到
DFA
的例子,步骤
3
又,合并状态
B1
及
B2
,我们得到上图,不过这个状态仍然是非确定性的,因为
advance_cycle_insn_decl
将触发两个状态迁移。看到这个状态
B12
甚至不能在前面自动机生成过程中存在。
图
77
:
NDFA
转换到
DFA
的例子,步骤
4
最后修改出的确定性自动机显示于上图。注意到这个确定性版本及非确定性版本,仅从指令发布机会的意义上而言,是相等的。
5917
static
void
5918
NDFA_to_DFA
(automaton_t
automaton)
5919
{
5920
state_t
start_state;
5921
state_t
state;
5922
decl_t
decl;
5923
vla_ptr_t state_stack;
5924
int i;
5925
int states_n;
5926
5927
VLA_PTR_CREATE (state_stack, 150, "state
stack");
5928
/* Create the start
state (empty state).
*/
5929
start_state = automaton->start_state;
5930
start_state->it_was_placed_in_stack_for_DFA_forming
= 1;
5931
VLA_PTR_ADD (state_stack, start_state);
5932
states_n = 1;
5933
while
(VLA_PTR_LENGTH (state_stack) != 0)
5934
{
5935
state = VLA_PTR (state_stack,
VLA_PTR_LENGTH (state_stack) - 1);
5936
VLA_PTR_SHORTEN (state_stack, 1);
5937
form_arcs_marked_by_insn
(state);
5938
for
(i = 0; i < description
->decls_num;
i++)
5939
{
5940
decl = description
->decls [i];
5941
if (decl->mode == dm_insn_reserv
5942
&& create_composed_state
5943
(state, DECL_INSN_RESERV
(decl)->arcs_marked_by_insn,
5944
&state_stack))
5945
{
5946
states_n++;
5947
if (progress_flag
&& states_n % 100 == 0)
5948
fprintf (stderr
, ".");
5949
}
5950
}
5951
}
5952
VLA_PTR_DELETE (state_stack);
5953
}
记住对于非确定性自动机,在我们上面的例子中,将评估
define_insn_reservation
中的每个替代;而对于确定性自动机,将仅评估第一个合格的替代。从这之后,这将形成很大的区别。事实上,当替代以确定性方式来处理时,构建出的自动机已经就是确定性的。
5787
static
void
5788
form_arcs_marked_by_insn
(state_t
state)
in
genautomata.c
5789
{
5790
decl_t
decl;
5791
arc_t arc;
5792
int i;
5793
5794
for
(i = 0; i < description
->decls_num; i++)
5795
{
5796
decl = description
->decls [i];
5797
if (decl->mode == dm_insn_reserv)
5798
DECL_INSN_RESERV (decl)->arcs_marked_by_insn
= NULL;
5799
}
5800
for
(arc =
first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5801
{
5802
if (arc->insn == NULL)
5803
abort ();
5804
arc->next_arc_marked_by_insn
5805
= arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5806
arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5807
}
5808
}
在跨越发布包含替代的指令类别的状态中,为了把这些特殊的迁移与其它确定性迁移区分开来,
form_arcs_marked_by_insn
将通过
next_arc_marked_by_insn
域链接这些迁移(以
arc
的形式)。
在非确定性的例子中,对于
start_state
将得到如下。
对于指令类别(
E|F
)
arcSF->next_arc_marked_by_insn = NULL (arcSF->to_state =
stateSF)
arcSF->insn->insn_reserv_decl->arcs_marked_by_insn = arcSF
arcSE->next_arc_marked_by_insn = arcSF (arcSE->to_state =
stateSE)
arcSE->insn->insn_reserv_decl->arcs_marked_by_insn = arcSE
(最后的值)
对于指令类别(
A|B|C
)
arcSC->next_arc_marked_by_insn = NULL (arcSC->to_state =
stateSC)
arcSC->insn->insn_reserv_decl->arcs_marked_by_insn = arcSC
arcSB->next_arc_marked_by_insn = arcSC (arcSB->to_state = stateSB)
arcSB->insn->insn_reserv_decl->arcs_marked_by_insn = arcSB
arcSA->next_arc_marked_by_insn = arcSB (arcSA->to_state =
stateSA)
arcSA->insn->insn_reserv_decl->arcs_marked_by_insn = arcSA
(最后的值)
(注意到上面的两部分被
state
的
arc
的
next_out_arc
域链接起来)
在确定性的例子中,对于
start_state
将得到如下。
对于指令类别
A
arcSA->next_arc_marked_by_insn = NULL (arcSA->to_state =
stateSA)
arcSA->insn->insn_reserv_decl->arcs_marked_by_insn = arcSA
对于指令类别
E
arcSE->next_arc_marked_by_insn = NULL (arcSE->to_state =
stateSE)
arcSE->insn->insn_reserv_decl->arcs_marked_by_insn = arcSE
(注意到上面的两部分被
state
的
arc
的
next_out_arc
域链接起来)
显示在下图,
insn (x1|x2|x3)
代表在
define_insn_reservation
中具有三个替代:
x1
,
x2
及
x3
的指令类别。在图中两个
arcs_marked_by_insn
是对应不同
insn_reserv_decl
的域
–
对应
define_insn_reservations
模式的
decl
。
图
78
:
构建
DFA
,阶段
2
现在在
state_stack
里仅是
state_start
。对于确定性自动机,
create_composed_state
是简单的,因为
next_arc_marked_by_insn
总是
NULL
(参见
5853
行的检查)。它将把在
5382
行获取的
to_state
压入
state_stack
并返回。现在在
state_stack
里,是
SA
,
SE
。
在非确定性自动机的例子中,域
component_states
用于所谓的复合状态(例如,上图中的状态
A12
,
B12
,
xy
)。对于具有替代
A
,
B
,
C
的指令类别来说,第一个参数
original_state
是
start_state
,而第二个参数
arcs_marked_by_insn
指向上图中的
arcs_marked_by_insn
,它是
insn_reserv_decl – define_insn_reservation
模式的
decl
,中的域。
5814
static
int
5815
create_composed_state
(state_t
original_state, arc_t arcs_marked_by_insn,
in
genautomata.c
5816
vla_ptr_t *state_stack)
5817
{
5818
state_t
state;
5819
alt_state_t alt_state, curr_alt_state;
5820
alt_state_t new_alt_state;
5821
arc_t curr_arc;
5822
arc_t next_arc;
5823
state_t
state_in_table;
5824
state_t
temp_state;
5825
alt_state_t canonical_alt_states_list;
5826
int alts_number;
5827
int new_state_p = 0;
5828
5829
if (arcs_marked_by_insn == NULL)
5830
return
new_state_p;
5831
if
(arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5832
state = arcs_marked_by_insn->to_state;
5833
else
5834
{
5835
if (!ndfa_flag
)
5836
abort ();
5837
/* Create
composed state.
*/
5838
state = get_free_state (0,
arcs_marked_by_insn->to_state->automaton);
5839
curr_alt_state = NULL;
5840
for
(curr_arc = arcs_marked_by_insn;
5841
curr_arc != NULL;
5842
curr_arc =
curr_arc->next_arc_marked_by_insn)
5843
if
(curr_arc->to_state->component_states == NULL)
5844
{
5845
new_alt_state = get_free_alt_state ();
5846
new_alt_state->next_alt_state =
curr_alt_state;
5847
new_alt_state->state =
curr_arc->to_state;
5848
curr_alt_state = new_alt_state;
5849
}
5850
else
5851
for
(alt_state = curr_arc->to_state->component_states;
5852
alt_state != NULL;
5853
alt_state =
alt_state->next_sorted_alt_state)
5854
{
5855
new_alt_state = get_free_alt_state
();
5856
new_alt_state->next_alt_state =
curr_alt_state;
5857
new_alt_state->state =
alt_state->state;
5858
if
(alt_state->state->component_states != NULL)
5859
abort ();
5860
curr_alt_state = new_alt_state;
5861
}
5862
/* There are
not identical sets in the alt state list.
*/
5863
canonical_alt_states_list = uniq_sort_alt_states
(curr_alt_state);
5864
if
(canonical_alt_states_list->next_sorted_alt_state == NULL)
5865
{
5866
temp_state = state;
5867
state =
canonical_alt_states_list->state;
5868
free_state (temp_state);
5869
}
5870
else
5871
{
5872
state->component_states =
canonical_alt_states_list;
5873
state_in_table = insert_state (state);
5874
if (state_in_table != state)
5875
{
5876
if
(!state_in_table->it_was_placed_in_stack_for_DFA_forming)
5877
abort ();
5878
free_state (state);
5879
state = state_in_table;
5880
}
5881
else
5882
{
5883
if
(state->it_was_placed_in_stack_for_DFA_forming)
5884
abort ();
5885
new_state_p = 1;
5886
for
(curr_alt_state = state->component_states;
5887
curr_alt_state != NULL;
5888
curr_alt_state =
curr_alt_state->next_sorted_alt_state)
5889
for
(curr_arc = first_out_arc (curr_alt_state->state);
5890
curr_arc != NULL;
5891
curr_arc = next_out_arc (curr_arc))
5892
add_arc
(state, curr_arc->to_state, curr_arc->insn, 1);
5893
}
5894
arcs_marked_by_insn->to_state =
state;
5895
for
(alts_number = 0,
5896
curr_arc =
arcs_marked_by_insn->next_arc_marked_by_insn;
5897
curr_arc != NULL;
5898
curr_arc = next_arc)
5899
{
5900
next_arc =
curr_arc->next_arc_marked_by_insn;
5901
remove_arc (original_state,
curr_arc);
5902
alts_number++;
5903
}
5904
arcs_marked_by_insn->state_alts =
alts_number;
5905
}
5906
}
5907
if
(!state->it_was_placed_in_stack_for_DFA_forming)
5908
{
5909
state->it_was_placed_in_stack_for_DFA_forming
= 1;
5910
VLA_PTR_ADD (*state_stack, state);
5911
}
5912
return
new_state_p;
5913
}
在我们例子中,
curr_alt_state
是一个链表,形如:
curr_alt_state(SA)->next_alt_state(SB)->
next_alt_state(SC)
。然后这个链表被传递给
uniq_sort_alt_states
,这个函数排序
alt_states_list
,并从这个链表中移去重复的
alt_state
。在这里,对于我们的非确定性例子,这个链表没有改变。
在
5864
行,如果
next_sorted_alt_state
不是
NULL
,那么在
5872
行的
state
是新构建的,它必然不出现在
state_table
里,因此我们进入
5882
行。在
create_composed_state
中构建的数据显示如下图。
图
79
:
构建
DFA
,阶段
3
正如我们之前提及的,一旦构建了新状态,当前状态的所有替代的迁移目标,就被设置为这个新状态的迁移目标。然后当前状态,在理论上,可以确定性地迁移到这个新状态,注意到在图中
arcSA
被留下了,蓝色的域被修改了;而其它用于当前状态替代的
arc
都被移除了。接着,这个新状态将被压入
state_stack
。然后在这个状态上重复上面的步骤。直到
state_stack
中没有状态(即,没有状态具有非确定性迁移),
NDFA_to_DFA
才退出。
相关文章推荐