From 5c8e2f8c2654560b341f887a74e9455c766f1a68 Mon Sep 17 00:00:00 2001 From: Karl Meakin Date: Sun, 15 Sep 2024 22:20:01 +0100 Subject: [PATCH] delete visitor based interpreter implementation Copyright (c) 2024, Arm Limited. Signed-off-by: Karl Meakin --- pulley/src/interp.rs | 566 ------------------------------------------- 1 file changed, 566 deletions(-) diff --git a/pulley/src/interp.rs b/pulley/src/interp.rs index 1a83e1b2a9db..c2c6a124a9f3 100644 --- a/pulley/src/interp.rs +++ b/pulley/src/interp.rs @@ -20,7 +20,6 @@ const DEFAULT_STACK_SIZE: usize = 1 << 20; // 1 MiB /// A virtual machine for interpreting Pulley bytecode. pub struct Vm { - decoder: Decoder, state: MachineState, } @@ -39,7 +38,6 @@ impl Vm { /// Create a new virtual machine with the given stack. pub fn with_stack(stack: Vec) -> Self { Self { - decoder: Decoder::new(), state: MachineState::with_stack(stack), } } @@ -595,567 +593,3 @@ enum Done { #[allow(dead_code)] HostCall, } - -struct InterpreterVisitor<'a> { - state: &'a mut MachineState, - pc: UnsafeBytecodeStream, -} - -impl InterpreterVisitor<'_> { - #[inline(always)] - 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) }; - } -} - -#[doc(hidden)] -impl OpVisitor for InterpreterVisitor<'_> { - type BytecodeStream = UnsafeBytecodeStream; - - fn bytecode(&mut self) -> &mut Self::BytecodeStream { - &mut self.pc - } - - type Return = ControlFlow; - - fn ret(&mut self) -> Self::Return { - if self.state[XReg::lr] == XRegVal::HOST_RETURN_ADDR { - 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}"); - 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); - ControlFlow::Continue(()) - } - - fn jump(&mut self, offset: PcRelOffset) -> Self::Return { - 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) - } - 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) - } - ControlFlow::Continue(()) - } - - fn br_if_xeq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { - let a = self.state[a].get_u32(); - let b = self.state[b].get_u32(); - if a == b { - self.pc_rel_jump(offset, 7) - } - ControlFlow::Continue(()) - } - - fn br_if_xneq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { - let a = self.state[a].get_u32(); - let b = self.state[b].get_u32(); - if a != b { - self.pc_rel_jump(offset, 7) - } - ControlFlow::Continue(()) - } - - fn br_if_xslt32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { - let a = self.state[a].get_i32(); - let b = self.state[b].get_i32(); - if a < b { - self.pc_rel_jump(offset, 7) - } - ControlFlow::Continue(()) - } - - fn br_if_xslteq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { - let a = self.state[a].get_i32(); - let b = self.state[b].get_i32(); - if a <= b { - self.pc_rel_jump(offset, 7) - } - ControlFlow::Continue(()) - } - - fn br_if_xult32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { - let a = self.state[a].get_u32(); - let b = self.state[b].get_u32(); - if a < b { - self.pc_rel_jump(offset, 7) - } - ControlFlow::Continue(()) - } - - fn br_if_xulteq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { - let a = self.state[a].get_u32(); - let b = self.state[b].get_u32(); - if a <= b { - self.pc_rel_jump(offset, 7) - } - ControlFlow::Continue(()) - } - - fn br_if_xeq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { - let a = self.state[a].get_u64(); - let b = self.state[b].get_u64(); - if a == b { - self.pc_rel_jump(offset, 7) - } - ControlFlow::Continue(()) - } - - fn br_if_xneq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { - let a = self.state[a].get_u64(); - let b = self.state[b].get_u64(); - if a != b { - self.pc_rel_jump(offset, 7) - } - ControlFlow::Continue(()) - } - - fn br_if_xslt64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { - let a = self.state[a].get_i64(); - let b = self.state[b].get_i64(); - if a < b { - self.pc_rel_jump(offset, 7) - } - ControlFlow::Continue(()) - } - - fn br_if_xslteq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { - let a = self.state[a].get_i64(); - let b = self.state[b].get_i64(); - if a <= b { - self.pc_rel_jump(offset, 7) - } - ControlFlow::Continue(()) - } - - fn br_if_xult64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { - let a = self.state[a].get_u64(); - let b = self.state[b].get_u64(); - if a < b { - self.pc_rel_jump(offset, 7) - } - ControlFlow::Continue(()) - } - - fn br_if_xulteq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { - let a = self.state[a].get_u64(); - let b = self.state[b].get_u64(); - if a <= b { - self.pc_rel_jump(offset, 7) - } - ControlFlow::Continue(()) - } - - fn xmov(&mut self, dst: XReg, src: XReg) -> Self::Return { - let val = self.state[src]; - self.state[dst] = val; - ControlFlow::Continue(()) - } - - fn fmov(&mut self, dst: FReg, src: FReg) -> Self::Return { - let val = self.state[src]; - self.state[dst] = val; - ControlFlow::Continue(()) - } - - fn vmov(&mut self, dst: VReg, src: VReg) -> Self::Return { - let val = self.state[src]; - self.state[dst] = val; - ControlFlow::Continue(()) - } - - fn xconst8(&mut self, dst: XReg, imm: i8) -> Self::Return { - self.state[dst].set_i64(i64::from(imm)); - ControlFlow::Continue(()) - } - - fn xconst16(&mut self, dst: XReg, imm: i16) -> Self::Return { - self.state[dst].set_i64(i64::from(imm)); - ControlFlow::Continue(()) - } - - fn xconst32(&mut self, dst: XReg, imm: i32) -> Self::Return { - self.state[dst].set_i64(i64::from(imm)); - ControlFlow::Continue(()) - } - - fn xconst64(&mut self, dst: XReg, imm: i64) -> Self::Return { - self.state[dst].set_i64(imm); - 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)); - 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)); - 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)); - 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)); - 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)); - 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)); - 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)); - 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)); - 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)); - 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)); - 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)); - 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)); - 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)); - 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)); - 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)); - 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)); - 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); - ControlFlow::Continue(()) - } - - fn load32_u_offset8(&mut self, dst: XReg, ptr: XReg, offset: i8) -> Self::Return { - let val = unsafe { - self.state[ptr] - .get_ptr::() - .byte_offset(offset.into()) - .read_unaligned() - }; - self.state[dst].set_u64(u64::from(val)); - ControlFlow::Continue(()) - } - - fn load32_s_offset8(&mut self, dst: XReg, ptr: XReg, offset: i8) -> Self::Return { - let val = unsafe { - self.state[ptr] - .get_ptr::() - .byte_offset(offset.into()) - .read_unaligned() - }; - self.state[dst].set_i64(i64::from(val)); - ControlFlow::Continue(()) - } - - fn load32_u_offset64(&mut self, dst: XReg, ptr: XReg, offset: i64) -> Self::Return { - let val = unsafe { - self.state[ptr] - .get_ptr::() - .byte_offset(offset as isize) - .read_unaligned() - }; - self.state[dst].set_u64(u64::from(val)); - ControlFlow::Continue(()) - } - - fn load32_s_offset64(&mut self, dst: XReg, ptr: XReg, offset: i64) -> Self::Return { - let val = unsafe { - self.state[ptr] - .get_ptr::() - .byte_offset(offset as isize) - .read_unaligned() - }; - self.state[dst].set_i64(i64::from(val)); - ControlFlow::Continue(()) - } - - fn load64_offset8(&mut self, dst: XReg, ptr: XReg, offset: i8) -> Self::Return { - let val = unsafe { - self.state[ptr] - .get_ptr::() - .byte_offset(offset.into()) - .read_unaligned() - }; - self.state[dst].set_u64(val); - ControlFlow::Continue(()) - } - - fn load64_offset64(&mut self, dst: XReg, ptr: XReg, offset: i64) -> Self::Return { - let val = unsafe { - self.state[ptr] - .get_ptr::() - .byte_offset(offset as isize) - .read_unaligned() - }; - self.state[dst].set_u64(val); - ControlFlow::Continue(()) - } - - fn store32(&mut self, ptr: XReg, src: XReg) -> Self::Return { - let ptr = self.state[ptr].get_ptr::(); - let val = self.state[src].get_u32(); - unsafe { - ptr::write_unaligned(ptr, val); - } - ControlFlow::Continue(()) - } - - fn store64(&mut self, ptr: XReg, src: XReg) -> Self::Return { - let ptr = self.state[ptr].get_ptr::(); - let val = self.state[src].get_u64(); - unsafe { - ptr::write_unaligned(ptr, val); - } - ControlFlow::Continue(()) - } - - fn store32_offset8(&mut self, ptr: XReg, offset: i8, src: XReg) -> Self::Return { - let val = self.state[src].get_u32(); - unsafe { - self.state[ptr] - .get_ptr::() - .byte_offset(offset.into()) - .write_unaligned(val); - } - ControlFlow::Continue(()) - } - - fn store64_offset8(&mut self, ptr: XReg, offset: i8, src: XReg) -> Self::Return { - let val = self.state[src].get_u64(); - unsafe { - self.state[ptr] - .get_ptr::() - .byte_offset(offset.into()) - .write_unaligned(val); - } - ControlFlow::Continue(()) - } - - fn store32_offset64(&mut self, ptr: XReg, offset: i64, src: XReg) -> Self::Return { - let val = self.state[src].get_u32(); - unsafe { - self.state[ptr] - .get_ptr::() - .byte_offset(offset as isize) - .write_unaligned(val); - } - ControlFlow::Continue(()) - } - - fn store64_offset64(&mut self, ptr: XReg, offset: i64, src: XReg) -> Self::Return { - let val = self.state[src].get_u64(); - unsafe { - self.state[ptr] - .get_ptr::() - .byte_offset(offset as isize) - .write_unaligned(val); - } - ControlFlow::Continue(()) - } - - fn xpush32(&mut self, src: XReg) -> Self::Return { - self.state.push(self.state[src].get_u32()); - ControlFlow::Continue(()) - } - - fn xpush32_many(&mut self, srcs: RegSet) -> Self::Return { - for src in srcs { - self.xpush32(src); - } - ControlFlow::Continue(()) - } - - fn xpush64(&mut self, src: XReg) -> Self::Return { - self.state.push(self.state[src].get_u64()); - ControlFlow::Continue(()) - } - - fn xpush64_many(&mut self, srcs: RegSet) -> Self::Return { - for src in srcs { - self.xpush64(src); - } - ControlFlow::Continue(()) - } - - fn xpop32(&mut self, dst: XReg) -> Self::Return { - let val = self.state.pop(); - self.state[dst].set_u32(val); - ControlFlow::Continue(()) - } - - fn xpop32_many(&mut self, dsts: RegSet) -> Self::Return { - for dst in dsts.into_iter().rev() { - self.xpop32(dst); - } - ControlFlow::Continue(()) - } - - fn xpop64(&mut self, dst: XReg) -> Self::Return { - let val = self.state.pop(); - self.state[dst].set_u64(val); - ControlFlow::Continue(()) - } - - fn xpop64_many(&mut self, dsts: RegSet) -> Self::Return { - for dst in dsts.into_iter().rev() { - self.xpop64(dst); - } - ControlFlow::Continue(()) - } - - /// `push lr; push fp; fp = sp` - fn push_frame(&mut self) -> Self::Return { - 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]; - ControlFlow::Continue(()) - } - - /// `sp = fp; pop fp; pop lr` - fn pop_frame(&mut self) -> Self::Return { - self.state[XReg::sp] = self.state[XReg::fp]; - let fp = self.state.pop(); - let lr = self.state.pop(); - self.state[XReg::fp].set_ptr::(fp); - self.state[XReg::lr].set_ptr::(lr); - 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()); - 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())); - 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())); - 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())); - ControlFlow::Continue(()) - } -} - -impl ExtendedOpVisitor for InterpreterVisitor<'_> { - fn nop(&mut self) -> Self::Return { - ControlFlow::Continue(()) - } - - fn trap(&mut self) -> Self::Return { - 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); - ControlFlow::Continue(()) - } -}