Skip to content

Commit

Permalink
winch(x64): Add support for return and unreachable
Browse files Browse the repository at this point in the history
  • Loading branch information
saulecabrera committed Jun 21, 2023
1 parent b05a09c commit a5892d9
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 3 deletions.
4 changes: 3 additions & 1 deletion fuzz/fuzz_targets/differential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,9 @@ fn winch_supports_module(module: &[u8]) -> bool {
| Block { .. }
| Loop { .. }
| Br { .. }
| BrIf { .. } => {}
| BrIf { .. }
| Unreachable { .. }
| Return { .. } => {}
_ => {
supported = false;
break 'main;
Expand Down
2 changes: 1 addition & 1 deletion winch/codegen/src/codegen/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ impl ControlStackFrame {
/// Returns the exit label of the current control stack frame. Note that
/// this is similar to [`ControlStackFrame::label`], with the only difference that it
/// returns `None` for `Loop` since its label doesn't represent an exit.
fn exit_label(&self) -> Option<&MachLabel> {
pub fn exit_label(&self) -> Option<&MachLabel> {
use ControlStackFrame::*;

match self {
Expand Down
4 changes: 4 additions & 0 deletions winch/codegen/src/isa/aarch64/masm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@ impl Masm for MacroAssembler {
fn jmp(&mut self, _target: MachLabel) {
todo!()
}

fn unreachable(&mut self) {
todo!()
}
}

impl MacroAssembler {
Expand Down
5 changes: 5 additions & 0 deletions winch/codegen/src/isa/x64/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -842,4 +842,9 @@ impl Assembler {
pub fn jmp(&mut self, target: MachLabel) {
self.emit(Inst::JmpKnown { dst: target });
}

/// Emit a trap instruction.
pub fn trap(&mut self, code: TrapCode) {
self.emit(Inst::Ud2 { trap_code: code })
}
}
7 changes: 6 additions & 1 deletion winch/codegen/src/isa/x64/masm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use crate::{
};
use crate::{isa::reg::Reg, masm::CalleeKind};
use cranelift_codegen::{
isa::x64::settings as x64_settings, settings, Final, MachBufferFinalized, MachLabel,
ir::TrapCode, isa::x64::settings as x64_settings, settings, Final, MachBufferFinalized,
MachLabel,
};

/// x64 MacroAssembler.
Expand Down Expand Up @@ -483,6 +484,10 @@ impl Masm for MacroAssembler {
context.free_gpr(tmp);
}
}

fn unreachable(&mut self) {
self.asm.trap(TrapCode::UnreachableCodeReached)
}
}

impl MacroAssembler {
Expand Down
3 changes: 3 additions & 0 deletions winch/codegen/src/masm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,4 +346,7 @@ pub(crate) trait MacroAssembler {

/// Emits and unconditional jump to the given label.
fn jmp(&mut self, target: MachLabel);

/// Emit an unreachable code trap.
fn unreachable(&mut self);
}
26 changes: 26 additions & 0 deletions winch/codegen/src/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ macro_rules! def_unsupported {
(emit Loop $($rest:tt)*) => {};
(emit Br $($rest:tt)*) => {};
(emit BrIf $($rest:tt)*) => {};
(emit Return $($rest:tt)*) => {};
(emit Unreachable $($rest:tt)*) => {};

(emit $unsupported:tt $($rest:tt)*) => {$($rest)*};
}
Expand Down Expand Up @@ -572,6 +574,30 @@ where
self.context.free_gpr(top);
}

fn visit_return(&mut self) {
// Grab the outermost frame, which is the function's body frame. We
// don't rely on `Self::control_at` since this frame is implicit and we
// know that it should exist at index 0.
let outermost = &mut self.control_frames[0];
self.context.pop_abi_results(outermost.result(), self.masm);
// The outermost should always be a block and therefore,
// should always have an exit label.
self.masm.jmp(*outermost.exit_label().unwrap());
// Set the frame as branch target so that
// we can bind the function's exit label.
outermost.set_as_target();
self.context.reachable = false;
}

fn visit_unreachable(&mut self) {
self.masm.unreachable();
self.context.reachable = false;
// Set the implicit outermost frame as target to perform the necessary
// stack clean up.
let outermost = &mut self.control_frames[0];
outermost.set_as_target();
}

wasmparser::for_each_operator!(def_unsupported);
}

Expand Down

0 comments on commit a5892d9

Please sign in to comment.