@@ -114,6 +114,24 @@ pub(crate) struct RealizedOp {
114114 pub ( crate ) owning_span : Option < Span > ,
115115}
116116
117+ pub enum InstructionSuccessor {
118+ /// Used for arbritary jumps, ECAL etc.... We cannot guarantee which
119+ /// instruction is going to be the next one
120+ Unknown ,
121+ /// Specifically to signal a return from call.
122+ /// This exists to allow each use to differentiate this from `Unknown` and empty vec.
123+ ReturnFromCall ,
124+ /// Vast majority of instruction will only have the next instruction,
125+ /// but jumps, function calls and other can actually have multiple
126+ /// instructions.
127+ /// usize here is the index of the instruction. So the next instruction
128+ /// is <current index> + 1.
129+ ///
130+ /// An empty vec is used for revert, contract return and the last instrution.
131+ /// Signals that no more instrctions will run.
132+ Many ( Vec < usize > ) ,
133+ }
134+
117135impl Op {
118136 /// Moves the stack pointer by the given amount (i.e. allocates stack memory)
119137 pub ( crate ) fn unowned_stack_allocate_memory (
@@ -721,16 +739,17 @@ impl Op {
721739 }
722740 }
723741
724- /// Returns a list of indices that represent the successors of `self` in the list of
725- /// instructions `ops`. For most instructions, the successor is simply the next instruction in
726- /// `ops`. The exceptions are jump instructions that can have arbitrary successors and RVRT
727- /// which does not have any successors.
742+ /// Returns all successors of `self`.
743+ /// For most instructions, the successor is simply the next instruction in
744+ /// `ops`, if there is any.
745+ /// Exceptions are jump instructions which can have arbitrary successors; RVRT
746+ /// which does not have any successors, and ECAL would can do pretty much anything.
728747 pub ( crate ) fn successors (
729748 & self ,
730749 index : usize ,
731750 ops : & [ Op ] ,
732751 label_to_index : & HashMap < Label , usize > ,
733- ) -> Vec < usize > {
752+ ) -> InstructionSuccessor {
734753 match & self . opcode {
735754 Either :: Left ( virt_op) => virt_op. successors ( index, ops) ,
736755 Either :: Right ( org_op) => org_op. successors ( index, ops, label_to_index) ,
@@ -1423,23 +1442,21 @@ impl<Reg: Clone + Eq + Ord + Hash> ControlFlowOp<Reg> {
14231442 index : usize ,
14241443 ops : & [ Op ] ,
14251444 label_to_index : & HashMap < Label , usize > ,
1426- ) -> Vec < usize > {
1427- use ControlFlowOp :: * ;
1428-
1445+ ) -> InstructionSuccessor {
14291446 let mut next_ops = Vec :: new ( ) ;
14301447
14311448 match self {
1432- Label ( _)
1433- | Comment
1434- | DataSectionOffsetPlaceholder
1435- | ConfigurablesOffsetPlaceholder
1436- | PushAll ( _)
1437- | PopAll ( _) => {
1449+ ControlFlowOp :: Label ( _)
1450+ | ControlFlowOp :: Comment
1451+ | ControlFlowOp :: DataSectionOffsetPlaceholder
1452+ | ControlFlowOp :: ConfigurablesOffsetPlaceholder
1453+ | ControlFlowOp :: PushAll ( _)
1454+ | ControlFlowOp :: PopAll ( _) => {
14381455 if index + 1 < ops. len ( ) {
14391456 next_ops. push ( index + 1 ) ;
14401457 }
14411458 }
1442- Jump { to, type_, .. } => match type_ {
1459+ ControlFlowOp :: Jump { to, type_, .. } => match type_ {
14431460 JumpType :: Unconditional => {
14441461 next_ops. push ( label_to_index[ to] ) ;
14451462 }
@@ -1455,12 +1472,11 @@ impl<Reg: Clone + Eq + Ord + Hash> ControlFlowOp<Reg> {
14551472 }
14561473 }
14571474 } ,
1458- // Impossible to know, so we return empty.
1459- JumpToAddr ( _) => { }
1460- ReturnFromCall { .. } => { }
1461- } ;
1475+ ControlFlowOp :: JumpToAddr ( _) => return InstructionSuccessor :: Unknown ,
1476+ ControlFlowOp :: ReturnFromCall { .. } => return InstructionSuccessor :: ReturnFromCall ,
1477+ }
14621478
1463- next_ops
1479+ InstructionSuccessor :: Many ( next_ops)
14641480 }
14651481}
14661482
0 commit comments