Skip to content

Commit 28b2ad4

Browse files
committed
implement translate_end_func method
1 parent 3af747e commit 28b2ad4

File tree

2 files changed

+106
-6
lines changed

2 files changed

+106
-6
lines changed

crates/wasmi/src/engine/translator/func2/instrs.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ impl InstrEncoder {
2525
/// Pushes an [`Instruction`] to the [`InstrEncoder`].
2626
///
2727
/// Returns an [`Instr`] that refers to the pushed [`Instruction`].
28-
#[must_use]
2928
pub fn push_instr(&mut self, instruction: Instruction) -> Instr {
3029
let instr = self.next_instr();
3130
self.instrs.push(instruction);

crates/wasmi/src/engine/translator/func2/mod.rs

Lines changed: 106 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ use self::{
2828
utils::Reset,
2929
};
3030
use crate::{
31-
core::{FuelCostsProvider, Typed, TypedVal},
31+
core::{FuelCostsProvider, Typed, TypedVal, ValType},
3232
engine::{
3333
translator::{utils::FuelInfo, Instr, LabelRef, LabelRegistry, WasmTranslator},
3434
BlockType,
3535
CompiledFuncEntity,
3636
TranslationError,
3737
},
38-
ir::{Const16, Instruction, Reg},
38+
ir::{BoundedRegSpan, Const16, Const32, Instruction, Reg, RegSpan},
3939
module::{FuncIdx, ModuleHeader, WasmiValueType},
4040
Engine,
4141
Error,
@@ -250,14 +250,115 @@ impl FuncTranslator {
250250

251251
/// Translates the end of the Wasm function enclosing Wasm `block`.
252252
fn translate_end_func(&mut self, frame: BlockControlFrame) -> Result<(), Error> {
253-
let fuel_info = match (frame.consume_fuel_instr(), &self.fuel_costs) {
254-
(Some(consume_fuel), Some(fuel_costs)) => {
253+
let fuel_info = match (&self.fuel_costs, frame.consume_fuel_instr()) {
254+
(Some(fuel_costs), Some(consume_fuel)) => {
255255
FuelInfo::some(fuel_costs.clone(), consume_fuel)
256256
}
257257
(None, None) => FuelInfo::None,
258258
_ => unreachable!(),
259259
};
260-
todo!()
260+
let len_results = frame.ty().len_results(&self.engine);
261+
if self.reachable && frame.is_branched_to() && len_results > 1 {
262+
let height = frame.height();
263+
let len_results = usize::from(len_results);
264+
for depth in 0..len_results {
265+
let result = self
266+
.layout
267+
.temp_to_reg(OperandIdx::from(height + len_results - depth - 1))?;
268+
match self.stack.operand_to_temp(depth) {
269+
Some(Operand::Local(operand)) => {
270+
let value = self.layout.local_to_reg(operand.local_index())?;
271+
self.instrs.push_instr(Instruction::copy(result, value));
272+
}
273+
Some(Operand::Immediate(operand)) => {
274+
let val = operand.val();
275+
let instr = match operand.ty() {
276+
ValType::I32 => Instruction::copy_imm32(result, i32::from(val)),
277+
ValType::I64 => {
278+
let val = i64::from(val);
279+
match <Const32<i64>>::try_from(val) {
280+
Ok(value) => Instruction::copy_i64imm32(result, value),
281+
Err(_) => {
282+
let value = self.layout.const_to_reg(val)?;
283+
Instruction::copy(result, value)
284+
}
285+
}
286+
}
287+
ValType::F32 => Instruction::copy_imm32(result, f32::from(val)),
288+
ValType::F64 => {
289+
let val = f64::from(val);
290+
match <Const32<f64>>::try_from(val) {
291+
Ok(value) => Instruction::copy_f64imm32(result, value),
292+
Err(_) => {
293+
let value = self.layout.const_to_reg(val)?;
294+
Instruction::copy(result, value)
295+
}
296+
}
297+
}
298+
ValType::V128 | ValType::FuncRef | ValType::ExternRef => {
299+
let value = self.layout.const_to_reg(val)?;
300+
Instruction::copy(result, value)
301+
}
302+
};
303+
self.instrs.push_instr(instr);
304+
}
305+
_ => {}
306+
}
307+
}
308+
}
309+
self.labels
310+
.pin_label(frame.label(), self.instrs.next_instr())
311+
.unwrap_or_else(|err| panic!("failed to pin label: {err}"));
312+
match len_results {
313+
0 => {
314+
self.instrs.push_instr(Instruction::Return);
315+
}
316+
1 => {
317+
let instr = match self.stack.peek(0) {
318+
Operand::Local(operand) => {
319+
let value = self.layout.local_to_reg(operand.local_index())?;
320+
Instruction::return_reg(value)
321+
}
322+
Operand::Temp(operand) => {
323+
let value = self.layout.temp_to_reg(operand.operand_index())?;
324+
Instruction::return_reg(value)
325+
}
326+
Operand::Immediate(operand) => {
327+
let val = operand.val();
328+
match operand.ty() {
329+
ValType::I32 => Instruction::return_imm32(i32::from(val)),
330+
ValType::I64 => match <Const32<i64>>::try_from(i64::from(val)) {
331+
Ok(value) => Instruction::return_i64imm32(value),
332+
Err(_) => {
333+
let value = self.layout.const_to_reg(val)?;
334+
Instruction::return_reg(value)
335+
}
336+
},
337+
ValType::F32 => Instruction::return_imm32(f32::from(val)),
338+
ValType::F64 => match <Const32<f64>>::try_from(f64::from(val)) {
339+
Ok(value) => Instruction::return_f64imm32(value),
340+
Err(_) => {
341+
let value = self.layout.const_to_reg(val)?;
342+
Instruction::return_reg(value)
343+
}
344+
},
345+
ValType::V128 | ValType::FuncRef | ValType::ExternRef => {
346+
let value = self.layout.const_to_reg(val)?;
347+
Instruction::return_reg(value)
348+
}
349+
}
350+
}
351+
};
352+
self.instrs.push_instr(instr);
353+
}
354+
n => {
355+
let height = frame.height();
356+
let result = self.layout.temp_to_reg(OperandIdx::from(height - 1))?;
357+
let values = BoundedRegSpan::new(RegSpan::new(result), len_results);
358+
self.instrs.push_instr(Instruction::return_span(values));
359+
}
360+
}
361+
Ok(())
261362
}
262363

263364
/// Translates the end of a Wasm `loop` control frame.

0 commit comments

Comments
 (0)