@@ -23,6 +23,25 @@ enum LocalPlacement {
23
23
}
24
24
impl CLRMethod {
25
25
fn name ( & self ) ->& str { & self . name }
26
+ fn crosses_bb_border ( & self , start : usize , end : usize ) ->bool {
27
+ false
28
+ }
29
+ fn backtrace_op_type ( & self , op_pos : usize ) ->Option < & VariableType > {
30
+ let mut op_pos: isize = ( op_pos as isize - 1 ) ;
31
+ let mut depth = -1 ;
32
+ while op_pos >= 0 {
33
+ depth += self . ops [ op_pos as usize ] . stack_change ( ) ;
34
+ if ( depth == 0 ) {
35
+ return self . op_types [ op_pos as usize ] . as_ref ( ) ;
36
+ }
37
+ op_pos -= 1 ;
38
+ }
39
+ None
40
+ }
41
+ // This function returns the type of a local variable if it is known
42
+ pub ( crate ) fn local_type ( & self , local : u32 ) ->Option < & VariableType > {
43
+ self . locals . get ( local as usize ) ?. as_ref ( )
44
+ }
26
45
pub ( crate ) fn get_arg_type ( & self , arg : u32 ) ->& VariableType {
27
46
& self . sig . inputs ( ) [ arg as usize ]
28
47
}
@@ -33,14 +52,52 @@ impl CLRMethod {
33
52
}
34
53
}
35
54
}
55
+ fn set_local_types ( & mut self ) {
56
+ for index in 0 ..( self . op_types . len ( ) ) {
57
+ if let BaseIR :: STLoc ( index) = self . ops [ index as usize ] {
58
+ if let Some ( var_type) = & self . op_types [ index as usize ] {
59
+ while self . locals . len ( ) < index as usize + 1 { self . locals . push ( None ) } ;
60
+ self . locals [ index as usize ] = Some ( var_type. clone ( ) ) ;
61
+ }
62
+ }
63
+ }
64
+ }
65
+ fn backtrace_types ( & mut self ) {
66
+ for index in 0 ..( self . op_types . len ( ) ) {
67
+ if let None = self . op_types [ index] {
68
+ self . op_types [ index] = self . backtrace_op_type ( index) . cloned ( ) ;
69
+ }
70
+ }
71
+ }
36
72
pub ( crate ) fn typecheck ( & mut self ) {
37
73
while self . op_types . len ( ) < self . ops . len ( ) {
38
74
self . op_types . push ( None ) ;
39
75
}
40
-
41
- self . set_trivial_types ( ) ;
76
+ for _ in 0 ..0x100 {
77
+ self . set_trivial_types ( ) ;
78
+ self . backtrace_types ( ) ;
79
+ self . set_local_types ( ) ;
80
+ if self . op_types . iter ( ) . all ( |t| t. is_some ( ) ) { break ; }
81
+ }
42
82
println ! ( "op_types:{:?}" , self . op_types) ;
43
83
}
84
+ pub ( crate ) fn locals_init ( & self ) ->IString {
85
+ if self . locals . is_empty ( ) {
86
+ return "" . into ( ) ;
87
+ }
88
+ let mut locals = String :: new ( ) ;
89
+ let mut locals_iter = self . locals . iter ( ) . enumerate ( ) ;
90
+ match locals_iter. next ( ) {
91
+ Some ( ( index, first) ) =>{
92
+ locals. push_str ( & format ! ( "\n \t \t [{index}] {loc_type}" , loc_type = first. as_ref( ) . expect( "UNRESOLVED LOCAL DURING IL EMISSION!" ) . il_name( ) ) )
93
+ }
94
+ None =>( ) ,
95
+ }
96
+ for ( index, local) in locals_iter{
97
+ locals. push_str ( & format ! ( ",\n \t \t [{index}] {loc_type}" , loc_type = local. as_ref( ) . expect( "UNRESOLVED LOCAL DURING IL EMISSION!" ) . il_name( ) ) )
98
+ }
99
+ format ! ( "\t .locals init({locals}\n \t )" ) . into ( )
100
+ }
44
101
pub ( crate ) fn into_il_ir ( & self ) ->String {
45
102
let output = self . sig . output ( ) . il_name ( ) ;
46
103
let mut arg_list = String :: new ( ) ;
@@ -57,20 +114,20 @@ impl CLRMethod {
57
114
for op in & self . ops {
58
115
ops_ir. push_str ( & op. clr_ir ( ) ) ;
59
116
}
60
- format ! ( ".method public static {output} {name}({arg_list}){{\n {ops_ir}}}\n " , name = self . name( ) )
117
+ format ! ( ".method public static {output} {name}({arg_list}){{\n {locals_init} \n { ops_ir}}}\n " , name = self . name( ) , locals_init = self . locals_init ( ) )
61
118
}
62
119
fn argc ( & self ) -> u32 {
63
120
self . sig . inputs ( ) . len ( ) as u32
64
121
}
65
122
fn remove_sl ( & mut self ) -> usize {
66
123
let mut opt_ops: Vec < BaseIR > = Vec :: with_capacity ( self . ops . len ( ) ) ;
67
- let mut ops_peek = self . ops . iter ( ) . peekable ( ) ;
68
- while let Some ( op ) = ops_peek. next ( ) {
124
+ let mut ops_peek = self . ops . iter ( ) . enumerate ( ) . peekable ( ) ;
125
+ while let Some ( ( index , op ) ) = ops_peek. next ( ) {
69
126
match op {
70
127
BaseIR :: STLoc ( local_id) => {
71
- if let Some ( BaseIR :: LDLoc ( other_id) ) = ops_peek. peek ( ) {
128
+ if let Some ( ( next_index , BaseIR :: LDLoc ( other_id) ) ) = ops_peek. peek ( ) {
72
129
//Ops store and the load the same value, being effectively a NOP.
73
- if local_id == other_id {
130
+ if local_id == other_id && ! self . crosses_bb_border ( index , * next_index ) {
74
131
ops_peek. next ( ) ;
75
132
continue ;
76
133
}
0 commit comments