Skip to content

Commit 2f7b0f5

Browse files
authored
pulley: Clarify documentation around CallIndirectHost (#9746)
Handling review comments from #9665 and fully updating documentation to reflect the mid-pr design shift to the currently-landed state.
1 parent 8fca662 commit 2f7b0f5

4 files changed

Lines changed: 33 additions & 18 deletions

File tree

cranelift/codegen/src/binemit/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ pub enum Reloc {
121121
S390xTlsGdCall,
122122

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

crates/cranelift/src/compiler.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,11 @@ impl Compiler {
147147
// Wasmtime itself.
148148
assert_eq!(signature.call_conv, self.isa.default_call_conv());
149149

150-
// If this target is actually pulley then a custom `call`
151-
// instruction is emitted. This will generate a new function with
152-
// the Cranelift-name of a "backend intrinsic" which is how the
153-
// Pulley backend models this special opcode that doesn't otherwise
154-
// map into the Cranelift set of opcodes.
150+
// If this target is actually pulley then the goal is to emit the custom
151+
// `call_indirect_host` pulley opcode. That's encoded in Cranelift as a
152+
// `call` instruction where the name is `colocated: false`. This will
153+
// force a pulley-specific relocation to get emitted in addition to
154+
// using the `call_indirect_host` instruction.
155155
let is_pulley = match self.isa.triple().architecture {
156156
target_lexicon::Architecture::Pulley32 => true,
157157
target_lexicon::Architecture::Pulley64 => true,

crates/cranelift/src/obj.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ impl<'a> ModuleTextBuilder<'a> {
206206
.unwrap();
207207
}
208208

209-
// This relocation is used to fill in which hostcall signature
210-
// is desired within the `call_indirect_host` opcode of Pulley
209+
// This relocation is used to fill in which hostcall id is
210+
// desired within the `call_indirect_host` opcode of Pulley
211211
// itself. The relocation target is the start of the instruction
212212
// and the goal is to insert the static signature number, `n`,
213213
// into the instruction.
@@ -225,10 +225,17 @@ impl<'a> ModuleTextBuilder<'a> {
225225
//
226226
// See the `test_call_indirect_host_width` in
227227
// `pulley/tests/all.rs` for this guarantee as well.
228+
#[cfg(feature = "pulley")]
228229
RelocationTarget::PulleyHostcall(n) => {
230+
use pulley_interpreter::encode::Encode;
231+
232+
assert_eq!(pulley_interpreter::CallIndirectHost::WIDTH, 4);
229233
let byte = u8::try_from(n).unwrap();
230234
self.text.write(reloc_offset + 3, &[byte]);
231235
}
236+
237+
#[cfg(not(feature = "pulley"))]
238+
RelocationTarget::PulleyHostcall(_) => unreachable!(),
232239
};
233240
}
234241
(symbol_id, off..off + body_len)

pulley/src/lib.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -222,18 +222,25 @@ macro_rules! for_each_extended_op {
222222
/// Do nothing.
223223
nop = Nop;
224224

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

0 commit comments

Comments
 (0)