@@ -411,6 +411,7 @@ pub(crate) struct InterpretedInstance {
411
411
compiled_offset : u32 ,
412
412
interrupt : InterruptKind ,
413
413
step_tracing : bool ,
414
+ unresolved_program_counter : Option < ProgramCounter > ,
414
415
}
415
416
416
417
impl InterpretedInstance {
@@ -433,6 +434,7 @@ impl InterpretedInstance {
433
434
compiled_offset : 0 ,
434
435
interrupt : InterruptKind :: Finished ,
435
436
step_tracing,
437
+ unresolved_program_counter : None ,
436
438
} ;
437
439
438
440
instance. initialize_module ( ) ;
@@ -715,9 +717,15 @@ impl InterpretedInstance {
715
717
} ;
716
718
717
719
self . program_counter = program_counter;
718
- self . compiled_offset = self . resolve_arbitrary_jump :: < DEBUG > ( program_counter) . unwrap_or ( TARGET_OUT_OF_RANGE ) ;
719
720
self . next_program_counter_changed = false ;
720
721
722
+ if let Some ( offset) = self . resolve_arbitrary_jump :: < DEBUG > ( program_counter) {
723
+ self . compiled_offset = offset;
724
+ } else {
725
+ self . compiled_offset = TARGET_OUT_OF_RANGE ;
726
+ self . unresolved_program_counter = Some ( program_counter) ;
727
+ }
728
+
721
729
if DEBUG {
722
730
log:: debug!( "Starting execution at: {} [{}]" , program_counter, self . compiled_offset) ;
723
731
}
@@ -1035,10 +1043,24 @@ impl<'a> Visitor<'a> {
1035
1043
) -> Option < Target > {
1036
1044
let s1 = self . get64 ( s1) ;
1037
1045
let s2 = self . get64 ( s2) ;
1038
- if callback ( s1, s2) {
1039
- Some ( target_true)
1046
+
1047
+ let ( packed_target, branch_taken) = if callback ( s1, s2) {
1048
+ ( target_true, true )
1049
+ } else {
1050
+ ( target_false, false )
1051
+ } ;
1052
+
1053
+ let ( is_jump_target_valid, target) = InterpretedInstance :: unpack_target ( NonZeroU32 :: new ( packed_target) . unwrap ( ) ) ;
1054
+
1055
+ if !is_jump_target_valid {
1056
+ self . inner . unresolved_program_counter = Some ( ProgramCounter ( target) ) ;
1057
+ if branch_taken {
1058
+ Some ( TARGET_INVALID_BRANCH )
1059
+ } else {
1060
+ Some ( TARGET_OUT_OF_RANGE )
1061
+ }
1040
1062
} else {
1041
- Some ( target_false )
1063
+ Some ( target )
1042
1064
}
1043
1065
}
1044
1066
@@ -1857,6 +1879,7 @@ fn trap_impl<const DEBUG: bool>(visitor: &mut Visitor, program_counter: ProgramC
1857
1879
visitor. inner . program_counter_valid = true ;
1858
1880
visitor. inner . next_program_counter = None ;
1859
1881
visitor. inner . next_program_counter_changed = true ;
1882
+ visitor. inner . unresolved_program_counter = None ;
1860
1883
visitor. inner . interrupt = InterruptKind :: Trap ;
1861
1884
None
1862
1885
}
@@ -1891,10 +1914,21 @@ macro_rules! handle_unresolved_branch {
1891
1914
}
1892
1915
1893
1916
let offset = $visitor. inner. compiled_offset;
1894
- let target_false = $visitor. inner. resolve_jump:: <DEBUG >( $tf) . unwrap_or( TARGET_OUT_OF_RANGE ) ;
1895
- let target_true = $visitor. inner. resolve_jump:: <DEBUG >( $tt) . unwrap_or( TARGET_INVALID_BRANCH ) ;
1917
+
1918
+ let packed_tt = if let Some ( target_true) = $visitor. inner. resolve_jump:: <DEBUG >( $tt) {
1919
+ InterpretedInstance :: pack_target( cast( target_true) . to_usize( ) , true ) . into( )
1920
+ } else {
1921
+ InterpretedInstance :: pack_target( cast( $tt. 0 ) . to_usize( ) , false ) . into( )
1922
+ } ;
1923
+
1924
+ let packed_tf = if let Some ( target_false) = $visitor. inner. resolve_jump:: <DEBUG >( $tf) {
1925
+ InterpretedInstance :: pack_target( cast( target_false) . to_usize( ) , true ) . into( )
1926
+ } else {
1927
+ InterpretedInstance :: pack_target( cast( $tf. 0 ) . to_usize( ) , false ) . into( )
1928
+ } ;
1929
+
1896
1930
$visitor. inner. compiled_handlers[ cast( offset) . to_usize( ) ] = cast_handler!( raw_handlers:: $name:: <DEBUG >) ;
1897
- $visitor. inner. compiled_args[ cast( offset) . to_usize( ) ] = Args :: $name( $s1, $s2, target_true , target_false ) ;
1931
+ $visitor. inner. compiled_args[ cast( offset) . to_usize( ) ] = Args :: $name( $s1, $s2, packed_tt , packed_tf ) ;
1898
1932
Some ( offset)
1899
1933
} } ;
1900
1934
}
@@ -1929,7 +1963,8 @@ define_interpreter! {
1929
1963
log:: trace!( "[{}]: trap (out of range)" , visitor. inner. compiled_offset) ;
1930
1964
}
1931
1965
1932
- let program_counter = visitor. inner. program_counter;
1966
+ let program_counter = visitor. inner. unresolved_program_counter. unwrap_or( visitor. inner. program_counter) ;
1967
+
1933
1968
let new_gas = visitor. inner. gas - i64 :: from( gas) ;
1934
1969
if new_gas < 0 {
1935
1970
not_enough_gas_impl:: <DEBUG >( visitor, program_counter, new_gas)
@@ -1960,8 +1995,11 @@ define_interpreter! {
1960
1995
log:: trace!( "[{}]: step (out of range)" , visitor. inner. compiled_offset) ;
1961
1996
}
1962
1997
1998
+ let program_counter = visitor. inner. unresolved_program_counter. unwrap_or( visitor. inner. program_counter) ;
1999
+
2000
+ visitor. inner. program_counter = program_counter;
1963
2001
visitor. inner. program_counter_valid = true ;
1964
- visitor. inner. next_program_counter = Some ( visitor . inner . program_counter) ;
2002
+ visitor. inner. next_program_counter = Some ( program_counter) ;
1965
2003
visitor. inner. next_program_counter_changed = false ;
1966
2004
visitor. inner. interrupt = InterruptKind :: Step ;
1967
2005
visitor. inner. compiled_offset += 1 ;
@@ -3640,6 +3678,7 @@ define_interpreter! {
3640
3678
} else {
3641
3679
visitor. inner. compiled_handlers[ cast( offset) . to_usize( ) ] = cast_handler!( raw_handlers:: jump:: <DEBUG >) ;
3642
3680
visitor. inner. compiled_args[ cast( offset) . to_usize( ) ] = Args :: jump( TARGET_OUT_OF_RANGE ) ;
3681
+ visitor. inner. unresolved_program_counter = Some ( jump_to) ;
3643
3682
Some ( TARGET_OUT_OF_RANGE )
3644
3683
}
3645
3684
}
0 commit comments