From 91045e120b8a8d531150b8f5e8ec0d19d895e6ac Mon Sep 17 00:00:00 2001 From: Karl Meakin Date: Fri, 6 Sep 2024 22:59:49 +0100 Subject: [PATCH] Replace `Continutation` with `ControlFlow` Copyright (c) 2024, Arm Limited. Signed-off-by: Karl Meakin --- pulley/src/interp.rs | 187 ++++++++++++++++++++----------------------- 1 file changed, 89 insertions(+), 98 deletions(-) diff --git a/pulley/src/interp.rs b/pulley/src/interp.rs index ca7945687044..40cdfed4139f 100644 --- a/pulley/src/interp.rs +++ b/pulley/src/interp.rs @@ -8,6 +8,7 @@ use alloc::string::ToString; use alloc::{vec, vec::Vec}; use core::fmt; use core::mem; +use core::ops::ControlFlow; use core::ops::{Index, IndexMut}; use core::ptr::{self, NonNull}; use sptr::Strict; @@ -126,22 +127,20 @@ impl Vm { }; loop { - let continuation = self.decoder.decode_one(&mut visitor).unwrap(); + let cf = self.decoder.decode_one(&mut visitor).unwrap(); // Really wish we had `feature(explicit_tail_calls)`... - match continuation { - Continuation::Continue => { - continue; - } + match cf { + ControlFlow::Continue(()) => continue, // Out-of-line slow paths marked `cold` and `inline(never)` to // improve codegen. - Continuation::Trap => { + ControlFlow::Break(Done::Trap) => { let pc = visitor.pc.as_ptr(); return self.trap(pc); } - Continuation::ReturnToHost => return self.return_to_host(), - Continuation::HostCall => return self.host_call(), + ControlFlow::Break(Done::ReturnToHost) => return self.return_to_host(), + ControlFlow::Break(Done::HostCall) => return self.host_call(), } } } @@ -597,9 +596,14 @@ impl MachineState { } } -enum Continuation { - Continue, +/// The reason the interpreter loop terminated. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +enum Done { + /// A `ret` instruction was executed and the call stack was empty. This is + /// how the loop normally ends. ReturnToHost, + + /// a `trap` instruction was executed. Trap, #[allow(dead_code)] @@ -613,10 +617,9 @@ struct InterpreterVisitor<'a> { impl InterpreterVisitor<'_> { #[inline(always)] - fn pc_rel_jump(&mut self, offset: PcRelOffset, inst_size: isize) -> Continuation { + fn pc_rel_jump(&mut self, offset: PcRelOffset, inst_size: isize) { let offset = isize::try_from(i32::from(offset)).unwrap(); self.pc = unsafe { self.pc.offset(offset - inst_size) }; - Continuation::Continue } } @@ -628,45 +631,45 @@ impl OpVisitor for InterpreterVisitor<'_> { &mut self.pc } - type Return = Continuation; + type Return = ControlFlow; fn ret(&mut self) -> Self::Return { if self.state[XReg::lr] == XRegVal::HOST_RETURN_ADDR { - Continuation::ReturnToHost + ControlFlow::Break(Done::ReturnToHost) } else { let return_addr = self.state[XReg::lr].get_ptr(); self.pc = unsafe { UnsafeBytecodeStream::new(NonNull::new_unchecked(return_addr)) }; // log::trace!("returning to {return_addr:#p}"); - Continuation::Continue + ControlFlow::Continue(()) } } fn call(&mut self, offset: PcRelOffset) -> Self::Return { let return_addr = self.pc.as_ptr(); self.state[XReg::lr].set_ptr(return_addr.as_ptr()); - self.pc_rel_jump(offset, 5) + self.pc_rel_jump(offset, 5); + ControlFlow::Continue(()) } fn jump(&mut self, offset: PcRelOffset) -> Self::Return { - self.pc_rel_jump(offset, 5) + self.pc_rel_jump(offset, 5); + ControlFlow::Continue(()) } fn br_if(&mut self, cond: XReg, offset: PcRelOffset) -> Self::Return { let cond = self.state[cond].get_u64(); if cond != 0 { self.pc_rel_jump(offset, 6) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn br_if_not(&mut self, cond: XReg, offset: PcRelOffset) -> Self::Return { let cond = self.state[cond].get_u64(); if cond == 0 { self.pc_rel_jump(offset, 6) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn br_if_xeq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { @@ -674,9 +677,8 @@ impl OpVisitor for InterpreterVisitor<'_> { let b = self.state[b].get_u32(); if a == b { self.pc_rel_jump(offset, 7) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn br_if_xneq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { @@ -684,9 +686,8 @@ impl OpVisitor for InterpreterVisitor<'_> { let b = self.state[b].get_u32(); if a != b { self.pc_rel_jump(offset, 7) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn br_if_xslt32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { @@ -694,9 +695,8 @@ impl OpVisitor for InterpreterVisitor<'_> { let b = self.state[b].get_i32(); if a < b { self.pc_rel_jump(offset, 7) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn br_if_xslteq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { @@ -704,9 +704,8 @@ impl OpVisitor for InterpreterVisitor<'_> { let b = self.state[b].get_i32(); if a <= b { self.pc_rel_jump(offset, 7) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn br_if_xult32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { @@ -714,9 +713,8 @@ impl OpVisitor for InterpreterVisitor<'_> { let b = self.state[b].get_u32(); if a < b { self.pc_rel_jump(offset, 7) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn br_if_xulteq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { @@ -724,9 +722,8 @@ impl OpVisitor for InterpreterVisitor<'_> { let b = self.state[b].get_u32(); if a <= b { self.pc_rel_jump(offset, 7) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn br_if_xeq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { @@ -734,9 +731,8 @@ impl OpVisitor for InterpreterVisitor<'_> { let b = self.state[b].get_u64(); if a == b { self.pc_rel_jump(offset, 7) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn br_if_xneq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { @@ -744,9 +740,8 @@ impl OpVisitor for InterpreterVisitor<'_> { let b = self.state[b].get_u64(); if a != b { self.pc_rel_jump(offset, 7) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn br_if_xslt64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { @@ -754,9 +749,8 @@ impl OpVisitor for InterpreterVisitor<'_> { let b = self.state[b].get_i64(); if a < b { self.pc_rel_jump(offset, 7) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn br_if_xslteq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { @@ -764,9 +758,8 @@ impl OpVisitor for InterpreterVisitor<'_> { let b = self.state[b].get_i64(); if a <= b { self.pc_rel_jump(offset, 7) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn br_if_xult64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { @@ -774,9 +767,8 @@ impl OpVisitor for InterpreterVisitor<'_> { let b = self.state[b].get_u64(); if a < b { self.pc_rel_jump(offset, 7) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn br_if_xulteq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { @@ -784,166 +776,165 @@ impl OpVisitor for InterpreterVisitor<'_> { let b = self.state[b].get_u64(); if a <= b { self.pc_rel_jump(offset, 7) - } else { - Continuation::Continue } + ControlFlow::Continue(()) } fn xmov(&mut self, dst: XReg, src: XReg) -> Self::Return { let val = self.state[src]; self.state[dst] = val; - Continuation::Continue + ControlFlow::Continue(()) } fn fmov(&mut self, dst: FReg, src: FReg) -> Self::Return { let val = self.state[src]; self.state[dst] = val; - Continuation::Continue + ControlFlow::Continue(()) } fn vmov(&mut self, dst: VReg, src: VReg) -> Self::Return { let val = self.state[src]; self.state[dst] = val; - Continuation::Continue + ControlFlow::Continue(()) } fn xconst8(&mut self, dst: XReg, imm: i8) -> Self::Return { self.state[dst].set_i64(i64::from(imm)); - Continuation::Continue + ControlFlow::Continue(()) } fn xconst16(&mut self, dst: XReg, imm: i16) -> Self::Return { self.state[dst].set_i64(i64::from(imm)); - Continuation::Continue + ControlFlow::Continue(()) } fn xconst32(&mut self, dst: XReg, imm: i32) -> Self::Return { self.state[dst].set_i64(i64::from(imm)); - Continuation::Continue + ControlFlow::Continue(()) } fn xconst64(&mut self, dst: XReg, imm: i64) -> Self::Return { self.state[dst].set_i64(imm); - Continuation::Continue + ControlFlow::Continue(()) } fn xadd32(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_u32(); let b = self.state[operands.src2].get_u32(); self.state[operands.dst].set_u32(a.wrapping_add(b)); - Continuation::Continue + ControlFlow::Continue(()) } fn xadd64(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_u64(); let b = self.state[operands.src2].get_u64(); self.state[operands.dst].set_u64(a.wrapping_add(b)); - Continuation::Continue + ControlFlow::Continue(()) } fn xeq64(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_u64(); let b = self.state[operands.src2].get_u64(); self.state[operands.dst].set_u64(u64::from(a == b)); - Continuation::Continue + ControlFlow::Continue(()) } fn xneq64(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_u64(); let b = self.state[operands.src2].get_u64(); self.state[operands.dst].set_u64(u64::from(a != b)); - Continuation::Continue + ControlFlow::Continue(()) } fn xslt64(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_i64(); let b = self.state[operands.src2].get_i64(); self.state[operands.dst].set_u64(u64::from(a < b)); - Continuation::Continue + ControlFlow::Continue(()) } fn xslteq64(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_i64(); let b = self.state[operands.src2].get_i64(); self.state[operands.dst].set_u64(u64::from(a <= b)); - Continuation::Continue + ControlFlow::Continue(()) } fn xult64(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_u64(); let b = self.state[operands.src2].get_u64(); self.state[operands.dst].set_u64(u64::from(a < b)); - Continuation::Continue + ControlFlow::Continue(()) } fn xulteq64(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_u64(); let b = self.state[operands.src2].get_u64(); self.state[operands.dst].set_u64(u64::from(a <= b)); - Continuation::Continue + ControlFlow::Continue(()) } fn xeq32(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_u32(); let b = self.state[operands.src2].get_u32(); self.state[operands.dst].set_u64(u64::from(a == b)); - Continuation::Continue + ControlFlow::Continue(()) } fn xneq32(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_u32(); let b = self.state[operands.src2].get_u32(); self.state[operands.dst].set_u64(u64::from(a != b)); - Continuation::Continue + ControlFlow::Continue(()) } fn xslt32(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_i32(); let b = self.state[operands.src2].get_i32(); self.state[operands.dst].set_u64(u64::from(a < b)); - Continuation::Continue + ControlFlow::Continue(()) } fn xslteq32(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_i32(); let b = self.state[operands.src2].get_i32(); self.state[operands.dst].set_u64(u64::from(a <= b)); - Continuation::Continue + ControlFlow::Continue(()) } fn xult32(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_u32(); let b = self.state[operands.src2].get_u32(); self.state[operands.dst].set_u64(u64::from(a < b)); - Continuation::Continue + ControlFlow::Continue(()) } fn xulteq32(&mut self, operands: BinaryOperands) -> Self::Return { let a = self.state[operands.src1].get_u32(); let b = self.state[operands.src2].get_u32(); self.state[operands.dst].set_u64(u64::from(a <= b)); - Continuation::Continue + ControlFlow::Continue(()) } fn load32_u(&mut self, dst: XReg, ptr: XReg) -> Self::Return { let ptr = self.state[ptr].get_ptr::(); let val = unsafe { ptr::read_unaligned(ptr) }; self.state[dst].set_u64(u64::from(val)); - Continuation::Continue + ControlFlow::Continue(()) } fn load32_s(&mut self, dst: XReg, ptr: XReg) -> Self::Return { let ptr = self.state[ptr].get_ptr::(); let val = unsafe { ptr::read_unaligned(ptr) }; self.state[dst].set_i64(i64::from(val)); - Continuation::Continue + ControlFlow::Continue(()) } fn load64(&mut self, dst: XReg, ptr: XReg) -> Self::Return { let ptr = self.state[ptr].get_ptr::(); let val = unsafe { ptr::read_unaligned(ptr) }; self.state[dst].set_u64(val); - Continuation::Continue + ControlFlow::Continue(()) } fn load32_u_offset8(&mut self, dst: XReg, ptr: XReg, offset: i8) -> Self::Return { @@ -954,7 +945,7 @@ impl OpVisitor for InterpreterVisitor<'_> { .read_unaligned() }; self.state[dst].set_u64(u64::from(val)); - Continuation::Continue + ControlFlow::Continue(()) } fn load32_s_offset8(&mut self, dst: XReg, ptr: XReg, offset: i8) -> Self::Return { @@ -965,7 +956,7 @@ impl OpVisitor for InterpreterVisitor<'_> { .read_unaligned() }; self.state[dst].set_i64(i64::from(val)); - Continuation::Continue + ControlFlow::Continue(()) } fn load32_u_offset64(&mut self, dst: XReg, ptr: XReg, offset: i64) -> Self::Return { @@ -976,7 +967,7 @@ impl OpVisitor for InterpreterVisitor<'_> { .read_unaligned() }; self.state[dst].set_u64(u64::from(val)); - Continuation::Continue + ControlFlow::Continue(()) } fn load32_s_offset64(&mut self, dst: XReg, ptr: XReg, offset: i64) -> Self::Return { @@ -987,7 +978,7 @@ impl OpVisitor for InterpreterVisitor<'_> { .read_unaligned() }; self.state[dst].set_i64(i64::from(val)); - Continuation::Continue + ControlFlow::Continue(()) } fn load64_offset8(&mut self, dst: XReg, ptr: XReg, offset: i8) -> Self::Return { @@ -998,7 +989,7 @@ impl OpVisitor for InterpreterVisitor<'_> { .read_unaligned() }; self.state[dst].set_u64(val); - Continuation::Continue + ControlFlow::Continue(()) } fn load64_offset64(&mut self, dst: XReg, ptr: XReg, offset: i64) -> Self::Return { @@ -1009,7 +1000,7 @@ impl OpVisitor for InterpreterVisitor<'_> { .read_unaligned() }; self.state[dst].set_u64(val); - Continuation::Continue + ControlFlow::Continue(()) } fn store32(&mut self, ptr: XReg, src: XReg) -> Self::Return { @@ -1018,7 +1009,7 @@ impl OpVisitor for InterpreterVisitor<'_> { unsafe { ptr::write_unaligned(ptr, val); } - Continuation::Continue + ControlFlow::Continue(()) } fn store64(&mut self, ptr: XReg, src: XReg) -> Self::Return { @@ -1027,7 +1018,7 @@ impl OpVisitor for InterpreterVisitor<'_> { unsafe { ptr::write_unaligned(ptr, val); } - Continuation::Continue + ControlFlow::Continue(()) } fn store32_offset8(&mut self, ptr: XReg, offset: i8, src: XReg) -> Self::Return { @@ -1038,7 +1029,7 @@ impl OpVisitor for InterpreterVisitor<'_> { .byte_offset(offset.into()) .write_unaligned(val); } - Continuation::Continue + ControlFlow::Continue(()) } fn store64_offset8(&mut self, ptr: XReg, offset: i8, src: XReg) -> Self::Return { @@ -1049,7 +1040,7 @@ impl OpVisitor for InterpreterVisitor<'_> { .byte_offset(offset.into()) .write_unaligned(val); } - Continuation::Continue + ControlFlow::Continue(()) } fn store32_offset64(&mut self, ptr: XReg, offset: i64, src: XReg) -> Self::Return { @@ -1060,7 +1051,7 @@ impl OpVisitor for InterpreterVisitor<'_> { .byte_offset(offset as isize) .write_unaligned(val); } - Continuation::Continue + ControlFlow::Continue(()) } fn store64_offset64(&mut self, ptr: XReg, offset: i64, src: XReg) -> Self::Return { @@ -1071,57 +1062,57 @@ impl OpVisitor for InterpreterVisitor<'_> { .byte_offset(offset as isize) .write_unaligned(val); } - Continuation::Continue + ControlFlow::Continue(()) } fn xpush32(&mut self, src: XReg) -> Self::Return { self.state.push(self.state[src].get_u32()); - Continuation::Continue + ControlFlow::Continue(()) } fn xpush32_many(&mut self, srcs: RegSet) -> Self::Return { for src in srcs { self.xpush32(src); } - Continuation::Continue + ControlFlow::Continue(()) } fn xpush64(&mut self, src: XReg) -> Self::Return { self.state.push(self.state[src].get_u64()); - Continuation::Continue + ControlFlow::Continue(()) } fn xpush64_many(&mut self, srcs: RegSet) -> Self::Return { for src in srcs { self.xpush64(src); } - Continuation::Continue + ControlFlow::Continue(()) } fn xpop32(&mut self, dst: XReg) -> Self::Return { let val = self.state.pop(); self.state[dst].set_u32(val); - Continuation::Continue + ControlFlow::Continue(()) } fn xpop32_many(&mut self, dsts: RegSet) -> Self::Return { for dst in dsts.into_iter().rev() { self.xpop32(dst); } - Continuation::Continue + ControlFlow::Continue(()) } fn xpop64(&mut self, dst: XReg) -> Self::Return { let val = self.state.pop(); self.state[dst].set_u64(val); - Continuation::Continue + ControlFlow::Continue(()) } fn xpop64_many(&mut self, dsts: RegSet) -> Self::Return { for dst in dsts.into_iter().rev() { self.xpop64(dst); } - Continuation::Continue + ControlFlow::Continue(()) } /// `push lr; push fp; fp = sp` @@ -1129,7 +1120,7 @@ impl OpVisitor for InterpreterVisitor<'_> { self.state.push(self.state[XReg::lr].get_ptr::()); self.state.push(self.state[XReg::fp].get_ptr::()); self.state[XReg::fp] = self.state[XReg::sp]; - Continuation::Continue + ControlFlow::Continue(()) } /// `sp = fp; pop fp; pop lr` @@ -1139,46 +1130,46 @@ impl OpVisitor for InterpreterVisitor<'_> { let lr = self.state.pop(); self.state[XReg::fp].set_ptr::(fp); self.state[XReg::lr].set_ptr::(lr); - Continuation::Continue + ControlFlow::Continue(()) } fn bitcast_int_from_float_32(&mut self, dst: XReg, src: FReg) -> Self::Return { let val = self.state[src].get_f32(); self.state[dst].set_u64(u32::from_ne_bytes(val.to_ne_bytes()).into()); - Continuation::Continue + ControlFlow::Continue(()) } fn bitcast_int_from_float_64(&mut self, dst: XReg, src: FReg) -> Self::Return { let val = self.state[src].get_f64(); self.state[dst].set_u64(u64::from_ne_bytes(val.to_ne_bytes())); - Continuation::Continue + ControlFlow::Continue(()) } fn bitcast_float_from_int_32(&mut self, dst: FReg, src: XReg) -> Self::Return { let val = self.state[src].get_u32(); self.state[dst].set_f32(f32::from_ne_bytes(val.to_ne_bytes())); - Continuation::Continue + ControlFlow::Continue(()) } fn bitcast_float_from_int_64(&mut self, dst: FReg, src: XReg) -> Self::Return { let val = self.state[src].get_u64(); self.state[dst].set_f64(f64::from_ne_bytes(val.to_ne_bytes())); - Continuation::Continue + ControlFlow::Continue(()) } } impl ExtendedOpVisitor for InterpreterVisitor<'_> { fn nop(&mut self) -> Self::Return { - Continuation::Continue + ControlFlow::Continue(()) } fn trap(&mut self) -> Self::Return { - Continuation::Trap + ControlFlow::Break(Done::Trap) } fn get_sp(&mut self, dst: XReg) -> Self::Return { let sp = self.state[XReg::sp].get_u64(); self.state[dst].set_u64(sp); - Continuation::Continue + ControlFlow::Continue(()) } }