Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
66d60c78
R
Rust
项目概览
int
/
Rust
12 个月 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
66d60c78
编写于
6月 09, 2016
作者:
S
Scott A Carr
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add control flow graph and algorithms. add dominator to mir
上级
fe96928d
变更
14
显示空白变更内容
内联
并排
Showing
14 changed file
with
871 addition
and
3 deletion
+871
-3
src/librustc/mir/cache.rs
src/librustc/mir/cache.rs
+1
-1
src/librustc/mir/repr.rs
src/librustc/mir/repr.rs
+40
-1
src/librustc_data_structures/control_flow_graph/dominators/mod.rs
...ustc_data_structures/control_flow_graph/dominators/mod.rs
+284
-0
src/librustc_data_structures/control_flow_graph/dominators/test.rs
...stc_data_structures/control_flow_graph/dominators/test.rs
+57
-0
src/librustc_data_structures/control_flow_graph/iterate/mod.rs
...ibrustc_data_structures/control_flow_graph/iterate/mod.rs
+70
-0
src/librustc_data_structures/control_flow_graph/iterate/test.rs
...brustc_data_structures/control_flow_graph/iterate/test.rs
+55
-0
src/librustc_data_structures/control_flow_graph/mod.rs
src/librustc_data_structures/control_flow_graph/mod.rs
+45
-0
src/librustc_data_structures/control_flow_graph/reachable/mod.rs
...rustc_data_structures/control_flow_graph/reachable/mod.rs
+65
-0
src/librustc_data_structures/control_flow_graph/reachable/test.rs
...ustc_data_structures/control_flow_graph/reachable/test.rs
+64
-0
src/librustc_data_structures/control_flow_graph/reference.rs
src/librustc_data_structures/control_flow_graph/reference.rs
+43
-0
src/librustc_data_structures/control_flow_graph/test.rs
src/librustc_data_structures/control_flow_graph/test.rs
+78
-0
src/librustc_data_structures/control_flow_graph/transpose.rs
src/librustc_data_structures/control_flow_graph/transpose.rs
+59
-0
src/librustc_data_structures/indexed_vec.rs
src/librustc_data_structures/indexed_vec.rs
+9
-1
src/librustc_data_structures/lib.rs
src/librustc_data_structures/lib.rs
+1
-0
未找到文件。
src/librustc/mir/cache.rs
浏览文件 @
66d60c78
...
...
@@ -15,7 +15,7 @@
use
rustc_serialize
as
serialize
;
#[derive(Clone)]
#[derive(Clone
,
Debug
)]
pub
struct
Cache
{
predecessors
:
RefCell
<
Option
<
IndexVec
<
BasicBlock
,
Vec
<
BasicBlock
>>>>
}
...
...
src/librustc/mir/repr.rs
浏览文件 @
66d60c78
...
...
@@ -12,6 +12,9 @@
use
middle
::
const_val
::
ConstVal
;
use
rustc_const_math
::{
ConstUsize
,
ConstInt
,
ConstMathErr
};
use
rustc_data_structures
::
indexed_vec
::{
IndexVec
,
Idx
};
use
rustc_data_structures
::
control_flow_graph
::
dominators
::{
Dominators
,
dominators
};
use
rustc_data_structures
::
control_flow_graph
::{
GraphPredecessors
,
GraphSuccessors
};
use
rustc_data_structures
::
control_flow_graph
::
ControlFlowGraph
;
use
hir
::
def_id
::
DefId
;
use
ty
::
subst
::
Substs
;
use
ty
::{
self
,
AdtDef
,
ClosureSubsts
,
FnOutput
,
Region
,
Ty
};
...
...
@@ -24,6 +27,7 @@
use
std
::
fmt
::{
self
,
Debug
,
Formatter
,
Write
};
use
std
::{
iter
,
u32
};
use
std
::
ops
::{
Index
,
IndexMut
};
use
std
::
vec
::
IntoIter
;
use
syntax
::
ast
::{
self
,
Name
};
use
syntax
::
codemap
::
Span
;
...
...
@@ -54,7 +58,7 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
}
/// Lowered representation of a single function.
#[derive(Clone,
RustcEncodable,
RustcDecodable)]
#[derive(Clone,
RustcEncodable,
RustcDecodable
,
Debug
)]
pub
struct
Mir
<
'tcx
>
{
/// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
/// that indexes into this vector.
...
...
@@ -145,6 +149,11 @@ pub fn predecessors_for(&self, bb: BasicBlock) -> Ref<Vec<BasicBlock>> {
Ref
::
map
(
self
.predecessors
(),
|
p
|
&
p
[
bb
])
}
#[inline]
pub
fn
dominators
(
&
self
)
->
Dominators
<
BasicBlock
>
{
dominators
(
self
)
}
/// Maps locals (Arg's, Var's, Temp's and ReturnPointer, in that order)
/// to their index in the whole list of locals. This is useful if you
/// want to treat all locals the same instead of repeating yourself.
...
...
@@ -1190,3 +1199,33 @@ fn node_to_string(node_id: ast::NodeId) -> String {
fn
item_path_str
(
def_id
:
DefId
)
->
String
{
ty
::
tls
::
with
(|
tcx
|
tcx
.item_path_str
(
def_id
))
}
impl
<
'tcx
>
ControlFlowGraph
for
Mir
<
'tcx
>
{
type
Node
=
BasicBlock
;
fn
num_nodes
(
&
self
)
->
usize
{
self
.basic_blocks
.len
()
}
fn
start_node
(
&
self
)
->
Self
::
Node
{
START_BLOCK
}
fn
predecessors
<
'graph
>
(
&
'graph
self
,
node
:
Self
::
Node
)
->
<
Self
as
GraphPredecessors
<
'graph
>>
::
Iter
{
self
.predecessors_for
(
node
)
.clone
()
.into_iter
()
}
fn
successors
<
'graph
>
(
&
'graph
self
,
node
:
Self
::
Node
)
->
<
Self
as
GraphSuccessors
<
'graph
>>
::
Iter
{
self
.basic_blocks
[
node
]
.terminator
()
.successors
()
.into_owned
()
.into_iter
()
}
}
impl
<
'a
,
'b
>
GraphPredecessors
<
'b
>
for
Mir
<
'a
>
{
type
Item
=
BasicBlock
;
type
Iter
=
IntoIter
<
BasicBlock
>
;
}
impl
<
'a
,
'b
>
GraphSuccessors
<
'b
>
for
Mir
<
'a
>
{
type
Item
=
BasicBlock
;
type
Iter
=
IntoIter
<
BasicBlock
>
;
}
src/librustc_data_structures/control_flow_graph/dominators/mod.rs
0 → 100644
浏览文件 @
66d60c78
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Algorithm citation:
//! A Simple, Fast Dominance Algorithm.
//! Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy
//! Rice Computer Science TS-06-33870
//! https://www.cs.rice.edu/~keith/EMBED/dom.pdf
use
super
::
ControlFlowGraph
;
use
super
::
iterate
::
reverse_post_order
;
use
super
::
super
::
indexed_vec
::{
IndexVec
,
Idx
};
use
std
::
fmt
;
#[cfg(test)]
mod
test
;
pub
fn
dominators
<
G
:
ControlFlowGraph
>
(
graph
:
&
G
)
->
Dominators
<
G
::
Node
>
{
let
start_node
=
graph
.start_node
();
let
rpo
=
reverse_post_order
(
graph
,
start_node
);
dominators_given_rpo
(
graph
,
&
rpo
)
}
pub
fn
dominators_given_rpo
<
G
:
ControlFlowGraph
>
(
graph
:
&
G
,
rpo
:
&
[
G
::
Node
])
->
Dominators
<
G
::
Node
>
{
let
start_node
=
graph
.start_node
();
assert_eq!
(
rpo
[
0
],
start_node
);
// compute the post order index (rank) for each node
let
mut
post_order_rank
:
IndexVec
<
G
::
Node
,
usize
>
=
IndexVec
::
from_elem_n
(
usize
::
default
(),
graph
.num_nodes
());
for
(
index
,
node
)
in
rpo
.iter
()
.rev
()
.cloned
()
.enumerate
()
{
post_order_rank
[
node
]
=
index
;
}
let
mut
immediate_dominators
:
IndexVec
<
G
::
Node
,
Option
<
G
::
Node
>>
=
IndexVec
::
from_elem_n
(
Option
::
default
(),
graph
.num_nodes
());
immediate_dominators
[
start_node
]
=
Some
(
start_node
);
let
mut
changed
=
true
;
while
changed
{
changed
=
false
;
for
&
node
in
&
rpo
[
1
..
]
{
let
mut
new_idom
=
None
;
for
pred
in
graph
.predecessors
(
node
)
{
if
immediate_dominators
[
pred
]
.is_some
()
{
// (*)
// (*) dominators for `pred` have been calculated
new_idom
=
intersect_opt
(
&
post_order_rank
,
&
immediate_dominators
,
new_idom
,
Some
(
pred
));
}
}
if
new_idom
!=
immediate_dominators
[
node
]
{
immediate_dominators
[
node
]
=
new_idom
;
changed
=
true
;
}
}
}
Dominators
{
post_order_rank
:
post_order_rank
,
immediate_dominators
:
immediate_dominators
,
}
}
fn
intersect_opt
<
Node
:
Idx
>
(
post_order_rank
:
&
IndexVec
<
Node
,
usize
>
,
immediate_dominators
:
&
IndexVec
<
Node
,
Option
<
Node
>>
,
node1
:
Option
<
Node
>
,
node2
:
Option
<
Node
>
)
->
Option
<
Node
>
{
match
(
node1
,
node2
)
{
(
None
,
None
)
=>
None
,
(
Some
(
n
),
None
)
|
(
None
,
Some
(
n
))
=>
Some
(
n
),
(
Some
(
n1
),
Some
(
n2
))
=>
Some
(
intersect
(
post_order_rank
,
immediate_dominators
,
n1
,
n2
)),
}
}
fn
intersect
<
Node
:
Idx
>
(
post_order_rank
:
&
IndexVec
<
Node
,
usize
>
,
immediate_dominators
:
&
IndexVec
<
Node
,
Option
<
Node
>>
,
mut
node1
:
Node
,
mut
node2
:
Node
)
->
Node
{
while
node1
!=
node2
{
while
post_order_rank
[
node1
]
<
post_order_rank
[
node2
]
{
node1
=
immediate_dominators
[
node1
]
.unwrap
();
}
while
post_order_rank
[
node2
]
<
post_order_rank
[
node1
]
{
node2
=
immediate_dominators
[
node2
]
.unwrap
();
}
}
return
node1
;
}
#[derive(Clone,
Debug)]
pub
struct
Dominators
<
N
:
Idx
>
{
post_order_rank
:
IndexVec
<
N
,
usize
>
,
immediate_dominators
:
IndexVec
<
N
,
Option
<
N
>>
,
}
impl
<
Node
:
Idx
>
Dominators
<
Node
>
{
pub
fn
is_reachable
(
&
self
,
node
:
Node
)
->
bool
{
self
.immediate_dominators
[
node
]
.is_some
()
}
pub
fn
immediate_dominator
(
&
self
,
node
:
Node
)
->
Node
{
assert
!
(
self
.is_reachable
(
node
),
"node {:?} is not reachable"
,
node
);
self
.immediate_dominators
[
node
]
.unwrap
()
}
pub
fn
dominators
(
&
self
,
node
:
Node
)
->
Iter
<
Node
>
{
assert
!
(
self
.is_reachable
(
node
),
"node {:?} is not reachable"
,
node
);
Iter
{
dominators
:
self
,
node
:
Some
(
node
),
}
}
pub
fn
is_dominated_by
(
&
self
,
node
:
Node
,
dom
:
Node
)
->
bool
{
// FIXME -- could be optimized by using post-order-rank
self
.dominators
(
node
)
.any
(|
n
|
n
==
dom
)
}
pub
fn
mutual_dominator_node
(
&
self
,
node1
:
Node
,
node2
:
Node
)
->
Node
{
assert
!
(
self
.is_reachable
(
node1
),
"node {:?} is not reachable"
,
node1
);
assert
!
(
self
.is_reachable
(
node2
),
"node {:?} is not reachable"
,
node2
);
intersect
::
<
Node
>
(
&
self
.post_order_rank
,
&
self
.immediate_dominators
,
node1
,
node2
)
}
pub
fn
mutual_dominator
<
I
>
(
&
self
,
iter
:
I
)
->
Option
<
Node
>
where
I
:
IntoIterator
<
Item
=
Node
>
{
let
mut
iter
=
iter
.into_iter
();
iter
.next
()
.map
(|
dom
|
iter
.fold
(
dom
,
|
dom
,
node
|
self
.mutual_dominator_node
(
dom
,
node
)))
}
pub
fn
all_immediate_dominators
(
&
self
)
->
&
IndexVec
<
Node
,
Option
<
Node
>>
{
&
self
.immediate_dominators
}
pub
fn
dominator_tree
(
&
self
)
->
DominatorTree
<
Node
>
{
let
elem
:
Vec
<
Node
>
=
Vec
::
new
();
let
mut
children
:
IndexVec
<
Node
,
Vec
<
Node
>>
=
IndexVec
::
from_elem_n
(
elem
,
self
.immediate_dominators
.len
());
let
mut
root
=
None
;
for
(
index
,
immed_dom
)
in
self
.immediate_dominators
.iter
()
.enumerate
()
{
let
node
=
Node
::
new
(
index
);
match
*
immed_dom
{
None
=>
{
// node not reachable
}
Some
(
immed_dom
)
=>
{
if
node
==
immed_dom
{
root
=
Some
(
node
);
}
else
{
children
[
immed_dom
]
.push
(
node
);
}
}
}
}
DominatorTree
{
root
:
root
.unwrap
(),
children
:
children
,
}
}
}
pub
struct
Iter
<
'dom
,
Node
:
Idx
+
'dom
>
{
dominators
:
&
'dom
Dominators
<
Node
>
,
node
:
Option
<
Node
>
,
}
impl
<
'dom
,
Node
:
Idx
>
Iterator
for
Iter
<
'dom
,
Node
>
{
type
Item
=
Node
;
fn
next
(
&
mut
self
)
->
Option
<
Self
::
Item
>
{
if
let
Some
(
node
)
=
self
.node
{
let
dom
=
self
.dominators
.immediate_dominator
(
node
);
if
dom
==
node
{
self
.node
=
None
;
// reached the root
}
else
{
self
.node
=
Some
(
dom
);
}
return
Some
(
node
);
}
else
{
return
None
;
}
}
}
pub
struct
DominatorTree
<
N
:
Idx
>
{
root
:
N
,
children
:
IndexVec
<
N
,
Vec
<
N
>>
,
}
impl
<
Node
:
Idx
>
DominatorTree
<
Node
>
{
pub
fn
root
(
&
self
)
->
Node
{
self
.root
}
pub
fn
children
(
&
self
,
node
:
Node
)
->
&
[
Node
]
{
&
self
.children
[
node
]
}
pub
fn
iter_children_of
(
&
self
,
node
:
Node
)
->
IterChildrenOf
<
Node
>
{
IterChildrenOf
{
tree
:
self
,
stack
:
vec!
[
node
],
}
}
}
pub
struct
IterChildrenOf
<
'iter
,
Node
:
Idx
+
'iter
>
{
tree
:
&
'iter
DominatorTree
<
Node
>
,
stack
:
Vec
<
Node
>
,
}
impl
<
'iter
,
Node
:
Idx
>
Iterator
for
IterChildrenOf
<
'iter
,
Node
>
{
type
Item
=
Node
;
fn
next
(
&
mut
self
)
->
Option
<
Node
>
{
if
let
Some
(
node
)
=
self
.stack
.pop
()
{
self
.stack
.extend
(
self
.tree
.children
(
node
));
Some
(
node
)
}
else
{
None
}
}
}
impl
<
Node
:
Idx
>
fmt
::
Debug
for
DominatorTree
<
Node
>
{
fn
fmt
(
&
self
,
fmt
:
&
mut
fmt
::
Formatter
)
->
Result
<
(),
fmt
::
Error
>
{
fmt
::
Debug
::
fmt
(
&
DominatorTreeNode
{
tree
:
self
,
node
:
self
.root
,
},
fmt
)
}
}
struct
DominatorTreeNode
<
'tree
,
Node
:
Idx
>
{
tree
:
&
'tree
DominatorTree
<
Node
>
,
node
:
Node
,
}
impl
<
'tree
,
Node
:
Idx
>
fmt
::
Debug
for
DominatorTreeNode
<
'tree
,
Node
>
{
fn
fmt
(
&
self
,
fmt
:
&
mut
fmt
::
Formatter
)
->
Result
<
(),
fmt
::
Error
>
{
let
subtrees
:
Vec
<
_
>
=
self
.tree
.children
(
self
.node
)
.iter
()
.map
(|
&
child
|
{
DominatorTreeNode
{
tree
:
self
.tree
,
node
:
child
,
}
})
.collect
();
fmt
.debug_tuple
(
""
)
.field
(
&
self
.node
)
.field
(
&
subtrees
)
.finish
()
}
}
src/librustc_data_structures/control_flow_graph/dominators/test.rs
0 → 100644
浏览文件 @
66d60c78
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
super
::
super
::
test
::
TestGraph
;
use
super
::
*
;
#[test]
fn
diamond
()
{
let
graph
=
TestGraph
::
new
(
0
,
&
[
(
0
,
1
),
(
0
,
2
),
(
1
,
3
),
(
2
,
3
),
]);
let
dominators
=
dominators
(
&
graph
);
let
immediate_dominators
=
dominators
.all_immediate_dominators
();
assert_eq!
(
immediate_dominators
[
0
],
Some
(
0
));
assert_eq!
(
immediate_dominators
[
1
],
Some
(
0
));
assert_eq!
(
immediate_dominators
[
2
],
Some
(
0
));
assert_eq!
(
immediate_dominators
[
3
],
Some
(
0
));
}
#[test]
fn
paper
()
{
// example from the paper:
let
graph
=
TestGraph
::
new
(
6
,
&
[
(
6
,
5
),
(
6
,
4
),
(
5
,
1
),
(
4
,
2
),
(
4
,
3
),
(
1
,
2
),
(
2
,
3
),
(
3
,
2
),
(
2
,
1
),
]);
let
dominators
=
dominators
(
&
graph
);
let
immediate_dominators
=
dominators
.all_immediate_dominators
();
assert_eq!
(
immediate_dominators
[
0
],
None
);
// <-- note that 0 is not in graph
assert_eq!
(
immediate_dominators
[
1
],
Some
(
6
));
assert_eq!
(
immediate_dominators
[
2
],
Some
(
6
));
assert_eq!
(
immediate_dominators
[
3
],
Some
(
6
));
assert_eq!
(
immediate_dominators
[
4
],
Some
(
6
));
assert_eq!
(
immediate_dominators
[
5
],
Some
(
6
));
assert_eq!
(
immediate_dominators
[
6
],
Some
(
6
));
}
src/librustc_data_structures/control_flow_graph/iterate/mod.rs
0 → 100644
浏览文件 @
66d60c78
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
super
::
ControlFlowGraph
;
use
super
::
super
::
indexed_vec
::
IndexVec
;
#[cfg(test)]
mod
test
;
pub
fn
post_order_from
<
G
:
ControlFlowGraph
>
(
graph
:
&
G
,
start_node
:
G
::
Node
)
->
Vec
<
G
::
Node
>
{
post_order_from_to
(
graph
,
start_node
,
None
)
}
pub
fn
post_order_from_to
<
G
:
ControlFlowGraph
>
(
graph
:
&
G
,
start_node
:
G
::
Node
,
end_node
:
Option
<
G
::
Node
>
)
->
Vec
<
G
::
Node
>
{
let
mut
visited
:
IndexVec
<
G
::
Node
,
bool
>
=
IndexVec
::
from_elem_n
(
false
,
graph
.num_nodes
());
let
mut
result
:
Vec
<
G
::
Node
>
=
Vec
::
with_capacity
(
graph
.num_nodes
());
if
let
Some
(
end_node
)
=
end_node
{
visited
[
end_node
]
=
true
;
}
post_order_walk
(
graph
,
start_node
,
&
mut
result
,
&
mut
visited
);
result
}
fn
post_order_walk
<
G
:
ControlFlowGraph
>
(
graph
:
&
G
,
node
:
G
::
Node
,
result
:
&
mut
Vec
<
G
::
Node
>
,
visited
:
&
mut
IndexVec
<
G
::
Node
,
bool
>
)
{
if
visited
[
node
]
{
return
;
}
visited
[
node
]
=
true
;
for
successor
in
graph
.successors
(
node
)
{
post_order_walk
(
graph
,
successor
,
result
,
visited
);
}
result
.push
(
node
);
}
pub
fn
pre_order_walk
<
G
:
ControlFlowGraph
>
(
graph
:
&
G
,
node
:
G
::
Node
,
result
:
&
mut
Vec
<
G
::
Node
>
,
visited
:
&
mut
IndexVec
<
G
::
Node
,
bool
>
)
{
if
visited
[
node
]
{
return
;
}
visited
[
node
]
=
true
;
result
.push
(
node
);
for
successor
in
graph
.successors
(
node
)
{
pre_order_walk
(
graph
,
successor
,
result
,
visited
);
}
}
pub
fn
reverse_post_order
<
G
:
ControlFlowGraph
>
(
graph
:
&
G
,
start_node
:
G
::
Node
)
->
Vec
<
G
::
Node
>
{
let
mut
vec
=
post_order_from
(
graph
,
start_node
);
vec
.reverse
();
vec
}
src/librustc_data_structures/control_flow_graph/iterate/test.rs
0 → 100644
浏览文件 @
66d60c78
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
super
::
super
::
test
::
TestGraph
;
use
super
::
super
::
transpose
::
TransposedGraph
;
use
super
::
*
;
#[test]
fn
diamond_post_order
()
{
let
graph
=
TestGraph
::
new
(
0
,
&
[
(
0
,
1
),
(
0
,
2
),
(
1
,
3
),
(
2
,
3
),
]);
let
result
=
post_order_from
(
&
graph
,
0
);
assert_eq!
(
result
,
vec!
[
3
,
1
,
2
,
0
]);
}
#[test]
fn
rev_post_order_inner_loop
()
{
// 0 -> 1 -> 2 -> 3 -> 5
// ^ ^ v |
// | 6 <- 4 |
// +-----------------+
let
graph
=
TestGraph
::
new
(
0
,
&
[
(
0
,
1
),
(
1
,
2
),
(
2
,
3
),
(
3
,
5
),
(
3
,
1
),
(
2
,
4
),
(
4
,
6
),
(
6
,
2
),
]);
let
rev_graph
=
TransposedGraph
::
new
(
&
graph
);
let
result
=
post_order_from_to
(
&
rev_graph
,
6
,
Some
(
2
));
assert_eq!
(
result
,
vec!
[
4
,
6
]);
let
result
=
post_order_from_to
(
&
rev_graph
,
3
,
Some
(
1
));
assert_eq!
(
result
,
vec!
[
4
,
6
,
2
,
3
]);
}
src/librustc_data_structures/control_flow_graph/mod.rs
0 → 100644
浏览文件 @
66d60c78
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
super
::
indexed_vec
::
Idx
;
pub
use
std
::
slice
::
Iter
;
pub
mod
dominators
;
pub
mod
iterate
;
pub
mod
reachable
;
mod
reference
;
pub
mod
transpose
;
#[cfg(test)]
mod
test
;
pub
trait
ControlFlowGraph
where
Self
:
for
<
'graph
>
GraphPredecessors
<
'graph
,
Item
=<
Self
as
ControlFlowGraph
>
::
Node
>
,
Self
:
for
<
'graph
>
GraphSuccessors
<
'graph
,
Item
=<
Self
as
ControlFlowGraph
>
::
Node
>
{
type
Node
:
Idx
;
fn
num_nodes
(
&
self
)
->
usize
;
fn
start_node
(
&
self
)
->
Self
::
Node
;
fn
predecessors
<
'graph
>
(
&
'graph
self
,
node
:
Self
::
Node
)
->
<
Self
as
GraphPredecessors
<
'graph
>>
::
Iter
;
fn
successors
<
'graph
>
(
&
'graph
self
,
node
:
Self
::
Node
)
->
<
Self
as
GraphSuccessors
<
'graph
>>
::
Iter
;
}
pub
trait
GraphPredecessors
<
'graph
>
{
type
Item
;
type
Iter
:
Iterator
<
Item
=
Self
::
Item
>
;
}
pub
trait
GraphSuccessors
<
'graph
>
{
type
Item
;
type
Iter
:
Iterator
<
Item
=
Self
::
Item
>
;
}
\ No newline at end of file
src/librustc_data_structures/control_flow_graph/reachable/mod.rs
0 → 100644
浏览文件 @
66d60c78
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Compute reachability using a simple dataflow propagation.
//! Store end-result in a big NxN bit matrix.
use
super
::
ControlFlowGraph
;
use
super
::
super
::
bitvec
::
BitVector
;
use
super
::
iterate
::
reverse_post_order
;
use
super
::
super
::
indexed_vec
::{
IndexVec
,
Idx
};
#[cfg(test)]
mod
test
;
pub
fn
reachable
<
G
:
ControlFlowGraph
>
(
graph
:
&
G
)
->
Reachability
<
G
::
Node
>
{
let
reverse_post_order
=
reverse_post_order
(
graph
,
graph
.start_node
());
reachable_given_rpo
(
graph
,
&
reverse_post_order
)
}
pub
fn
reachable_given_rpo
<
G
:
ControlFlowGraph
>
(
graph
:
&
G
,
reverse_post_order
:
&
[
G
::
Node
])
->
Reachability
<
G
::
Node
>
{
let
mut
reachability
=
Reachability
::
new
(
graph
);
let
mut
changed
=
true
;
while
changed
{
changed
=
false
;
for
&
node
in
reverse_post_order
.iter
()
.rev
()
{
// every node can reach itself
changed
|
=
reachability
.bits
[
node
]
.insert
(
node
.index
());
// and every pred can reach everything node can reach
for
pred
in
graph
.predecessors
(
node
)
{
let
nodes_bits
=
reachability
.bits
[
node
]
.clone
();
changed
|
=
reachability
.bits
[
pred
]
.insert_all
(
&
nodes_bits
);
}
}
}
reachability
}
pub
struct
Reachability
<
Node
:
Idx
>
{
bits
:
IndexVec
<
Node
,
BitVector
>
,
}
impl
<
Node
:
Idx
>
Reachability
<
Node
>
{
fn
new
<
G
:
ControlFlowGraph
>
(
graph
:
&
G
)
->
Self
{
let
num_nodes
=
graph
.num_nodes
();
Reachability
{
bits
:
IndexVec
::
from_elem_n
(
BitVector
::
new
(
num_nodes
),
num_nodes
),
}
}
pub
fn
can_reach
(
&
self
,
source
:
Node
,
target
:
Node
)
->
bool
{
let
bit
:
usize
=
target
.index
();
self
.bits
[
source
]
.contains
(
bit
)
}
}
src/librustc_data_structures/control_flow_graph/reachable/test.rs
0 → 100644
浏览文件 @
66d60c78
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
super
::
super
::
test
::
TestGraph
;
use
super
::
*
;
#[test]
fn
test1
()
{
// 0 -> 1 -> 2 -> 3
// ^ v
// 6 <- 4 -> 5
let
graph
=
TestGraph
::
new
(
0
,
&
[
(
0
,
1
),
(
1
,
2
),
(
2
,
3
),
(
2
,
4
),
(
4
,
5
),
(
4
,
6
),
(
6
,
1
),
]);
let
reachable
=
reachable
(
&
graph
);
assert
!
((
0
..
6
)
.all
(|
i
|
reachable
.can_reach
(
0
,
i
)));
assert
!
((
1
..
6
)
.all
(|
i
|
reachable
.can_reach
(
1
,
i
)));
assert
!
((
1
..
6
)
.all
(|
i
|
reachable
.can_reach
(
2
,
i
)));
assert
!
((
1
..
6
)
.all
(|
i
|
reachable
.can_reach
(
4
,
i
)));
assert
!
((
1
..
6
)
.all
(|
i
|
reachable
.can_reach
(
6
,
i
)));
assert
!
(
reachable
.can_reach
(
3
,
3
));
assert
!
(
!
reachable
.can_reach
(
3
,
5
));
assert
!
(
!
reachable
.can_reach
(
5
,
3
));
}
/// use bigger indices to cross between words in the bit set
#[test]
fn
test2
()
{
// 30 -> 31 -> 32 -> 33
// ^ v
// 36 <- 34 -> 35
let
graph
=
TestGraph
::
new
(
30
,
&
[
(
30
,
31
),
(
31
,
32
),
(
32
,
33
),
(
32
,
34
),
(
34
,
35
),
(
34
,
36
),
(
36
,
31
),
]);
let
reachable
=
reachable
(
&
graph
);
assert
!
((
30
..
36
)
.all
(|
i
|
reachable
.can_reach
(
30
,
i
)));
assert
!
((
31
..
36
)
.all
(|
i
|
reachable
.can_reach
(
31
,
i
)));
assert
!
((
31
..
36
)
.all
(|
i
|
reachable
.can_reach
(
32
,
i
)));
assert
!
((
31
..
36
)
.all
(|
i
|
reachable
.can_reach
(
34
,
i
)));
assert
!
((
31
..
36
)
.all
(|
i
|
reachable
.can_reach
(
36
,
i
)));
assert
!
(
reachable
.can_reach
(
33
,
33
));
assert
!
(
!
reachable
.can_reach
(
33
,
35
));
assert
!
(
!
reachable
.can_reach
(
35
,
33
));
}
src/librustc_data_structures/control_flow_graph/reference.rs
0 → 100644
浏览文件 @
66d60c78
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
super
::
*
;
impl
<
'graph
,
G
:
ControlFlowGraph
>
ControlFlowGraph
for
&
'graph
G
{
type
Node
=
G
::
Node
;
fn
num_nodes
(
&
self
)
->
usize
{
(
**
self
)
.num_nodes
()
}
fn
start_node
(
&
self
)
->
Self
::
Node
{
(
**
self
)
.start_node
()
}
fn
predecessors
<
'iter
>
(
&
'iter
self
,
node
:
Self
::
Node
)
->
<
Self
as
GraphPredecessors
<
'iter
>>
::
Iter
{
(
**
self
)
.predecessors
(
node
)
}
fn
successors
<
'iter
>
(
&
'iter
self
,
node
:
Self
::
Node
)
->
<
Self
as
GraphSuccessors
<
'iter
>>
::
Iter
{
(
**
self
)
.successors
(
node
)
}
}
impl
<
'iter
,
'graph
,
G
:
ControlFlowGraph
>
GraphPredecessors
<
'iter
>
for
&
'graph
G
{
type
Item
=
G
::
Node
;
type
Iter
=
<
G
as
GraphPredecessors
<
'iter
>>
::
Iter
;
}
impl
<
'iter
,
'graph
,
G
:
ControlFlowGraph
>
GraphSuccessors
<
'iter
>
for
&
'graph
G
{
type
Item
=
G
::
Node
;
type
Iter
=
<
G
as
GraphSuccessors
<
'iter
>>
::
Iter
;
}
src/librustc_data_structures/control_flow_graph/test.rs
0 → 100644
浏览文件 @
66d60c78
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
std
::
collections
::
HashMap
;
use
std
::
cmp
::
max
;
use
std
::
slice
;
use
std
::
iter
;
use
super
::{
ControlFlowGraph
,
GraphPredecessors
,
GraphSuccessors
};
pub
struct
TestGraph
{
num_nodes
:
usize
,
start_node
:
usize
,
successors
:
HashMap
<
usize
,
Vec
<
usize
>>
,
predecessors
:
HashMap
<
usize
,
Vec
<
usize
>>
,
}
impl
TestGraph
{
pub
fn
new
(
start_node
:
usize
,
edges
:
&
[(
usize
,
usize
)])
->
Self
{
let
mut
graph
=
TestGraph
{
num_nodes
:
start_node
+
1
,
start_node
:
start_node
,
successors
:
HashMap
::
new
(),
predecessors
:
HashMap
::
new
()
};
for
&
(
source
,
target
)
in
edges
{
graph
.num_nodes
=
max
(
graph
.num_nodes
,
source
+
1
);
graph
.num_nodes
=
max
(
graph
.num_nodes
,
target
+
1
);
graph
.successors
.entry
(
source
)
.or_insert
(
vec!
[])
.push
(
target
);
graph
.predecessors
.entry
(
target
)
.or_insert
(
vec!
[])
.push
(
source
);
}
for
node
in
0
..
graph
.num_nodes
{
graph
.successors
.entry
(
node
)
.or_insert
(
vec!
[]);
graph
.predecessors
.entry
(
node
)
.or_insert
(
vec!
[]);
}
graph
}
}
impl
ControlFlowGraph
for
TestGraph
{
type
Node
=
usize
;
fn
start_node
(
&
self
)
->
usize
{
self
.start_node
}
fn
num_nodes
(
&
self
)
->
usize
{
self
.num_nodes
}
fn
predecessors
<
'graph
>
(
&
'graph
self
,
node
:
usize
)
->
<
Self
as
GraphPredecessors
<
'graph
>>
::
Iter
{
self
.predecessors
[
&
node
]
.iter
()
.cloned
()
}
fn
successors
<
'graph
>
(
&
'graph
self
,
node
:
usize
)
->
<
Self
as
GraphSuccessors
<
'graph
>>
::
Iter
{
self
.successors
[
&
node
]
.iter
()
.cloned
()
}
}
impl
<
'graph
>
GraphPredecessors
<
'graph
>
for
TestGraph
{
type
Item
=
usize
;
type
Iter
=
iter
::
Cloned
<
slice
::
Iter
<
'graph
,
usize
>>
;
}
impl
<
'graph
>
GraphSuccessors
<
'graph
>
for
TestGraph
{
type
Item
=
usize
;
type
Iter
=
iter
::
Cloned
<
slice
::
Iter
<
'graph
,
usize
>>
;
}
src/librustc_data_structures/control_flow_graph/transpose.rs
0 → 100644
浏览文件 @
66d60c78
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
super
::
*
;
pub
struct
TransposedGraph
<
G
:
ControlFlowGraph
>
{
base_graph
:
G
,
start_node
:
G
::
Node
,
}
impl
<
G
:
ControlFlowGraph
>
TransposedGraph
<
G
>
{
pub
fn
new
(
base_graph
:
G
)
->
Self
{
let
start_node
=
base_graph
.start_node
();
Self
::
with_start
(
base_graph
,
start_node
)
}
pub
fn
with_start
(
base_graph
:
G
,
start_node
:
G
::
Node
)
->
Self
{
TransposedGraph
{
base_graph
:
base_graph
,
start_node
:
start_node
}
}
}
impl
<
G
:
ControlFlowGraph
>
ControlFlowGraph
for
TransposedGraph
<
G
>
{
type
Node
=
G
::
Node
;
fn
num_nodes
(
&
self
)
->
usize
{
self
.base_graph
.num_nodes
()
}
fn
start_node
(
&
self
)
->
Self
::
Node
{
self
.start_node
}
fn
predecessors
<
'graph
>
(
&
'graph
self
,
node
:
Self
::
Node
)
->
<
Self
as
GraphPredecessors
<
'graph
>>
::
Iter
{
self
.base_graph
.successors
(
node
)
}
fn
successors
<
'graph
>
(
&
'graph
self
,
node
:
Self
::
Node
)
->
<
Self
as
GraphSuccessors
<
'graph
>>
::
Iter
{
self
.base_graph
.predecessors
(
node
)
}
}
impl
<
'graph
,
G
:
ControlFlowGraph
>
GraphPredecessors
<
'graph
>
for
TransposedGraph
<
G
>
{
type
Item
=
G
::
Node
;
type
Iter
=
<
G
as
GraphSuccessors
<
'graph
>>
::
Iter
;
}
impl
<
'graph
,
G
:
ControlFlowGraph
>
GraphSuccessors
<
'graph
>
for
TransposedGraph
<
G
>
{
type
Item
=
G
::
Node
;
type
Iter
=
<
G
as
GraphPredecessors
<
'graph
>>
::
Iter
;
}
src/librustc_data_structures/indexed_vec.rs
浏览文件 @
66d60c78
...
...
@@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
std
::
fmt
::
Debug
;
use
std
::
iter
::{
self
,
FromIterator
};
use
std
::
slice
;
use
std
::
marker
::
PhantomData
;
...
...
@@ -20,7 +21,7 @@
/// Represents some newtyped `usize` wrapper.
///
/// (purpose: avoid mixing indexes for different bitvector domains.)
pub
trait
Idx
:
Copy
+
'static
{
pub
trait
Idx
:
Copy
+
'static
+
Eq
+
Debug
{
fn
new
(
usize
)
->
Self
;
fn
index
(
self
)
->
usize
;
}
...
...
@@ -76,6 +77,13 @@ pub fn from_elem<S>(elem: T, universe: &IndexVec<I, S>) -> Self
IndexVec
{
raw
:
vec!
[
elem
;
universe
.len
()],
_
marker
:
PhantomData
}
}
#[inline]
pub
fn
from_elem_n
(
elem
:
T
,
n
:
usize
)
->
Self
where
T
:
Clone
{
IndexVec
{
raw
:
vec!
[
elem
;
n
],
_
marker
:
PhantomData
}
}
#[inline]
pub
fn
push
(
&
mut
self
,
d
:
T
)
->
I
{
let
idx
=
I
::
new
(
self
.len
());
...
...
src/librustc_data_structures/lib.rs
浏览文件 @
66d60c78
...
...
@@ -50,6 +50,7 @@
pub
mod
fnv
;
pub
mod
tuple_slice
;
pub
mod
veccell
;
pub
mod
control_flow_graph
;
// See comments in src/librustc/lib.rs
#[doc(hidden)]
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录