Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cranelift/codegen/src/binemit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ pub enum Reloc {
S390xTlsGdCall,

/// Pulley - call a host function indirectly where the embedder resolving
/// this relocation needs to fill in the expected signature.
/// this relocation needs to fill the 8-bit immediate that's part of the
/// `call_indirect_host` opcode (an opaque identifier used by the host).
PulleyCallIndirectHost,
}

Expand Down
10 changes: 5 additions & 5 deletions crates/cranelift/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,11 @@ impl Compiler {
// Wasmtime itself.
assert_eq!(signature.call_conv, self.isa.default_call_conv());

// If this target is actually pulley then a custom `call`
// instruction is emitted. This will generate a new function with
// the Cranelift-name of a "backend intrinsic" which is how the
// Pulley backend models this special opcode that doesn't otherwise
// map into the Cranelift set of opcodes.
// If this target is actually pulley then the goal is to emit the custom
// `call_indirect_host` pulley opcode. That's encoded in Cranelift as a
// `call` instruction where the name is `colocated: false`. This will
// force a pulley-specific relocation to get emitted in addition to
// using the `call_indirect_host` instruction.
let is_pulley = match self.isa.triple().architecture {
target_lexicon::Architecture::Pulley32 => true,
target_lexicon::Architecture::Pulley64 => true,
Expand Down
11 changes: 9 additions & 2 deletions crates/cranelift/src/obj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ impl<'a> ModuleTextBuilder<'a> {
.unwrap();
}

// This relocation is used to fill in which hostcall signature
// is desired within the `call_indirect_host` opcode of Pulley
// This relocation is used to fill in which hostcall id is
// desired within the `call_indirect_host` opcode of Pulley
// itself. The relocation target is the start of the instruction
// and the goal is to insert the static signature number, `n`,
// into the instruction.
Expand All @@ -225,10 +225,17 @@ impl<'a> ModuleTextBuilder<'a> {
//
// See the `test_call_indirect_host_width` in
// `pulley/tests/all.rs` for this guarantee as well.
#[cfg(feature = "pulley")]
RelocationTarget::PulleyHostcall(n) => {
use pulley_interpreter::encode::Encode;

assert_eq!(pulley_interpreter::CallIndirectHost::WIDTH, 4);
let byte = u8::try_from(n).unwrap();
self.text.write(reloc_offset + 3, &[byte]);
}

#[cfg(not(feature = "pulley"))]
RelocationTarget::PulleyHostcall(_) => unreachable!(),
};
}
(symbol_id, off..off + body_len)
Expand Down
27 changes: 17 additions & 10 deletions pulley/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,18 +222,25 @@ macro_rules! for_each_extended_op {
/// Do nothing.
nop = Nop;

/// A special opcode to use an indirect function call to reenter the
/// host from the interpreter.
/// A special opcode to halt interpreter execution and yield control
/// back to the host.
///
/// This is used to implement host intrinsics such as `memory.grow`
/// for example where that needs to reenter the host from the
/// interpreter.
/// This opcode results in `DoneReason::CallIndirectHost` where the
/// `id` here is shepherded along to the embedder. It's up to the
/// embedder to determine what to do with the `id` and the current
/// state of registers and the stack.
///
/// The `sig` immediate here is the Nth signature in the
/// `for_each_host_signature!` macro below. The 0th "argument", in
/// register x0, is the function pointer that's being called and all
/// further arguments follow after that in registers.
call_indirect_host = CallIndirectHost { sig: u8 };
/// In Wasmtime this is used to implement interpreter-to-host calls.
/// This is modeled as a `call` instruction where the first
/// parameter is the native function pointer to invoke and all
/// remaining parameters for the native function are in following
/// parameter positions (e.g. `x1`, `x2`, ...). The results of the
/// host call are then store in `x0`.
///
/// Handling this in Wasmtime is done through a "relocation" which
/// is resolved at link-time when raw bytecode from Cranelift is
/// assembled into the final object that Wasmtime will interpret.
call_indirect_host = CallIndirectHost { id: u8 };
}
};
}
Expand Down