1
1
use std:: collections:: HashMap ;
2
2
3
- // A program composed of basic blocks.
4
- // (BB index of main program, list of BBs, mapping of label -> BB index)
5
- pub type BBProgram = ( Option < usize > , Vec < BasicBlock > , HashMap < String , usize > ) ;
6
-
7
- #[ derive( Debug ) ]
8
- pub struct BasicBlock {
9
- pub instrs : Vec < bril_rs:: Code > ,
10
- pub exit : Vec < usize > ,
3
+ pub struct FuncInfo {
4
+ pub args : Vec < bril_rs:: Argument > ,
5
+ pub return_type : Option < bril_rs:: Type > ,
6
+ pub start_block : usize ,
11
7
}
12
8
13
- impl BasicBlock {
14
- fn new ( ) -> BasicBlock {
15
- BasicBlock {
16
- instrs : Vec :: new ( ) ,
17
- exit : Vec :: new ( ) ,
9
+ impl FuncInfo {
10
+ fn new ( f : & bril_rs:: Function , start_block : usize ) -> FuncInfo {
11
+ FuncInfo {
12
+ args : f. args . clone ( ) ,
13
+ return_type : f. return_type . clone ( ) ,
14
+ start_block : start_block,
18
15
}
19
16
}
20
17
}
21
18
22
- pub fn find_basic_blocks ( prog : bril_rs:: Program ) -> BBProgram {
23
- let mut main_fn = None ;
24
- let mut blocks = Vec :: new ( ) ;
25
- let mut labels = HashMap :: new ( ) ;
19
+ // A program represented as basic blocks.
20
+ pub struct BBProgram {
21
+ pub blocks : Vec < BasicBlock > ,
22
+
23
+ // Map from label name to index in `blocks` of the block named by that label.
24
+ pub label_index : HashMap < String , usize > ,
25
+
26
+ // Map from function name to information needed during runtime about the
27
+ // function.
28
+ pub func_index : HashMap < String , FuncInfo > ,
29
+ }
30
+
31
+ impl BBProgram {
32
+ pub fn new ( prog : bril_rs:: Program ) -> BBProgram {
33
+ let mut bbprog = BBProgram {
34
+ blocks : vec ! [ ] ,
35
+ label_index : HashMap :: new ( ) ,
36
+ func_index : HashMap :: new ( ) ,
37
+ } ;
38
+ for func in prog. functions {
39
+ bbprog. add_func_bbs ( func) ;
40
+ }
41
+ bbprog
42
+ }
26
43
27
- let mut bb_helper = |func : bril_rs:: Function | -> usize {
44
+ fn add_func_bbs ( & mut self , func : bril_rs:: Function ) -> usize {
45
+ self
46
+ . func_index
47
+ . insert ( func. name . clone ( ) , FuncInfo :: new ( & func, self . blocks . len ( ) ) ) ;
28
48
let mut curr_block = BasicBlock :: new ( ) ;
29
- let root_block = blocks. len ( ) ;
49
+ let root_block = self . blocks . len ( ) ;
30
50
let mut curr_label = None ;
51
+
31
52
for instr in func. instrs . into_iter ( ) {
32
53
match instr {
33
54
bril_rs:: Code :: Label { ref label } => {
34
55
if !curr_block. instrs . is_empty ( ) {
35
- blocks. push ( curr_block) ;
56
+ self . blocks . push ( curr_block) ;
36
57
if let Some ( old_label) = curr_label {
37
- labels . insert ( old_label, blocks. len ( ) - 1 ) ;
58
+ self . label_index . insert ( old_label, self . blocks . len ( ) - 1 ) ;
38
59
}
39
60
curr_block = BasicBlock :: new ( ) ;
40
61
}
@@ -46,9 +67,9 @@ pub fn find_basic_blocks(prog: bril_rs::Program) -> BBProgram {
46
67
|| op == bril_rs:: EffectOps :: Return =>
47
68
{
48
69
curr_block. instrs . push ( instr) ;
49
- blocks. push ( curr_block) ;
70
+ self . blocks . push ( curr_block) ;
50
71
if let Some ( l) = curr_label {
51
- labels . insert ( l, blocks. len ( ) - 1 ) ;
72
+ self . label_index . insert ( l, self . blocks . len ( ) - 1 ) ;
52
73
curr_label = None ;
53
74
}
54
75
curr_block = BasicBlock :: new ( ) ;
@@ -60,22 +81,36 @@ pub fn find_basic_blocks(prog: bril_rs::Program) -> BBProgram {
60
81
}
61
82
62
83
if !curr_block. instrs . is_empty ( ) {
63
- blocks. push ( curr_block) ;
84
+ // If we are here, the function ends without an explicit ret. To make
85
+ // processing easier, push a Return op onto the last block.
86
+ curr_block. instrs . push ( RET . clone ( ) ) ;
87
+ self . blocks . push ( curr_block) ;
64
88
if let Some ( l) = curr_label {
65
- labels . insert ( l, blocks. len ( ) - 1 ) ;
89
+ self . label_index . insert ( l, self . blocks . len ( ) - 1 ) ;
66
90
}
67
91
}
68
-
69
92
root_block
70
- } ;
93
+ }
94
+ }
95
+
96
+ #[ derive( Debug ) ]
97
+ pub struct BasicBlock {
98
+ pub instrs : Vec < bril_rs:: Code > ,
99
+ pub exit : Vec < usize > ,
100
+ }
71
101
72
- for func in prog . functions . into_iter ( ) {
73
- let func_name = func . name . clone ( ) ;
74
- let func_block = bb_helper ( func ) ;
75
- if func_name == "main" {
76
- main_fn = Some ( func_block ) ;
102
+ impl BasicBlock {
103
+ fn new ( ) -> BasicBlock {
104
+ BasicBlock {
105
+ instrs : Vec :: new ( ) ,
106
+ exit : Vec :: new ( ) ,
77
107
}
78
108
}
79
-
80
- ( main_fn, blocks, labels)
81
109
}
110
+
111
+ const RET : bril_rs:: Code = bril_rs:: Code :: Instruction ( bril_rs:: Instruction :: Effect {
112
+ op : bril_rs:: EffectOps :: Return ,
113
+ args : vec ! [ ] ,
114
+ funcs : vec ! [ ] ,
115
+ labels : vec ! [ ] ,
116
+ } ) ;
0 commit comments