wasmi/engine/executor/instrs/
copy.rs1use super::{Executor, InstructionPtr};
2use crate::{
3 core::UntypedVal,
4 engine::utils::unreachable_unchecked,
5 ir::{AnyConst32, Const32, FixedSlotSpan, Op, Slot, SlotSpan},
6};
7use core::slice;
8
9impl Executor<'_> {
10 fn execute_copy_impl<T>(&mut self, result: Slot, value: T, f: fn(&mut Self, T) -> UntypedVal) {
12 let value = f(self, value);
13 self.set_stack_slot(result, value);
14 self.next_instr()
15 }
16
17 pub fn execute_copy(&mut self, result: Slot, value: Slot) {
19 self.execute_copy_impl(result, value, |this, value| this.get_stack_slot(value))
20 }
21
22 pub fn execute_copy_2(&mut self, results: FixedSlotSpan<2>, values: [Slot; 2]) {
24 self.execute_copy_2_impl(results, values);
25 self.next_instr()
26 }
27
28 fn execute_copy_2_impl(&mut self, results: FixedSlotSpan<2>, values: [Slot; 2]) {
30 let result0 = results.span().head();
31 let result1 = result0.next();
32 let tmp = self.get_stack_slot(values[1]);
34 self.set_stack_slot(result0, self.get_stack_slot(values[0]));
35 self.set_stack_slot(result1, tmp);
36 }
37
38 pub fn execute_copy_imm32(&mut self, result: Slot, value: AnyConst32) {
40 self.execute_copy_impl(result, value, |_, value| UntypedVal::from(u32::from(value)))
41 }
42
43 pub fn execute_copy_i64imm32(&mut self, result: Slot, value: Const32<i64>) {
45 self.execute_copy_impl(result, value, |_, value| UntypedVal::from(i64::from(value)))
46 }
47
48 pub fn execute_copy_f64imm32(&mut self, result: Slot, value: Const32<f64>) {
50 self.execute_copy_impl(result, value, |_, value| UntypedVal::from(f64::from(value)))
51 }
52
53 pub fn execute_copy_span(&mut self, results: SlotSpan, values: SlotSpan, len: u16) {
61 self.execute_copy_span_impl(results, values, len);
62 self.next_instr();
63 }
64
65 pub fn execute_copy_span_impl(&mut self, results: SlotSpan, values: SlotSpan, len: u16) {
67 let results = results.iter(len);
68 let values = values.iter(len);
69 for (result, value) in results.into_iter().zip(values.into_iter()) {
70 let value = self.get_stack_slot(value);
71 self.set_stack_slot(result, value);
72 }
73 }
74
75 pub fn execute_copy_many(&mut self, results: SlotSpan, values: [Slot; 2]) {
77 self.ip.add(1);
78 self.ip = self.execute_copy_many_impl(self.ip, results, &values);
79 self.next_instr()
80 }
81
82 pub fn execute_copy_many_impl(
84 &mut self,
85 ip: InstructionPtr,
86 results: SlotSpan,
87 values: &[Slot],
88 ) -> InstructionPtr {
89 let mut ip = ip;
90 let mut result = results.head();
91 let mut copy_values = |values: &[Slot]| {
92 for &value in values {
93 let value = self.get_stack_slot(value);
94 self.set_stack_slot(result, value);
95 result = result.next();
96 }
97 };
98 copy_values(values);
99 while let Op::SlotList { regs } = ip.get() {
100 copy_values(regs);
101 ip.add(1);
102 }
103 let values = match ip.get() {
104 Op::Slot { slot } => slice::from_ref(slot),
105 Op::Slot2 { slots } => slots,
106 Op::Slot3 { slots } => slots,
107 unexpected => {
108 unsafe {
110 unreachable_unchecked!("expected slot-list finalizer but found: {unexpected:?}")
111 }
112 }
113 };
114 copy_values(values);
115 ip
116 }
117}