@@ -23,6 +23,25 @@ enum LocalPlacement {
2323}
2424impl CLRMethod {
2525 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+ }
2645 pub ( crate ) fn get_arg_type ( & self , arg : u32 ) ->& VariableType {
2746 & self . sig . inputs ( ) [ arg as usize ]
2847 }
@@ -33,14 +52,52 @@ impl CLRMethod {
3352 }
3453 }
3554 }
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+ }
3672 pub ( crate ) fn typecheck ( & mut self ) {
3773 while self . op_types . len ( ) < self . ops . len ( ) {
3874 self . op_types . push ( None ) ;
3975 }
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+ }
4282 println ! ( "op_types:{:?}" , self . op_types) ;
4383 }
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+ }
44101 pub ( crate ) fn into_il_ir ( & self ) ->String {
45102 let output = self . sig . output ( ) . il_name ( ) ;
46103 let mut arg_list = String :: new ( ) ;
@@ -57,20 +114,20 @@ impl CLRMethod {
57114 for op in & self . ops {
58115 ops_ir. push_str ( & op. clr_ir ( ) ) ;
59116 }
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 ( ) )
61118 }
62119 fn argc ( & self ) -> u32 {
63120 self . sig . inputs ( ) . len ( ) as u32
64121 }
65122 fn remove_sl ( & mut self ) -> usize {
66123 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 ( ) {
69126 match op {
70127 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 ( ) {
72129 //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 ) {
74131 ops_peek. next ( ) ;
75132 continue ;
76133 }
0 commit comments