Skip to content

Commit

Permalink
wasmtime-interface-types: always use multi-value Wasm
Browse files Browse the repository at this point in the history
And remove the return pointer hacks that work around the lack of multi-value.
  • Loading branch information
fitzgen committed Oct 11, 2019
1 parent bed55de commit 5cfd0b7
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 51 deletions.
6 changes: 5 additions & 1 deletion misc/wasmtime-rust/macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result<TokenStream> {
isa_builder.finish(#root::cranelift_codegen::settings::Flags::new(flag_builder))
};

let mut cx = #root::wasmtime_jit::Context::with_isa(isa);
let mut cx = #root::wasmtime_jit::Context::with_isa(isa)
.with_features(#root::wasmtime_jit::Features {
multi_value: true,
..Default::default()
});
let data = #root::wasmtime_interface_types::ModuleData::new(&bytes)?;
let handle = cx.instantiate_module(None, &bytes)?;

Expand Down
56 changes: 6 additions & 50 deletions wasmtime-interface-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,26 +108,12 @@ impl ModuleData {
let incoming = binding.param_bindings()?;
let outgoing = binding.result_bindings()?;

// We have a magical dummy binding which indicates that this wasm
// function is using a return pointer. This is a total hack around
// multi-value, and we really should just implement multi-value in
// wasm-bindgen. In the meantime though this synthesizes a return
// pointer going as the first argument and translating outgoing
// arguments reads from the return pointer.
let (base, incoming, outgoing) = if uses_retptr(&outgoing) {
(Some(8), &incoming[1..], &outgoing[1..])
} else {
(None, incoming.as_slice(), outgoing.as_slice())
};
let mut wasm_args = translate_incoming(cx, handle, &incoming, base.is_some() as u32, args)?;
if let Some(n) = base {
wasm_args.insert(0, RuntimeValue::I32(n as i32));
}
let wasm_args = translate_incoming(cx, handle, &incoming, args)?;
let wasm_results = match cx.invoke(handle, export, &wasm_args)? {
ActionOutcome::Returned { values } => values,
ActionOutcome::Trapped { message } => bail!("trapped: {}", message),
};
translate_outgoing(cx, handle, &outgoing, base, &wasm_results)
translate_outgoing(cx, handle, &outgoing, &wasm_results)
}

/// Returns an appropriate binding for the `name` export in this module
Expand Down Expand Up @@ -211,14 +197,8 @@ impl ExportBinding<'_> {
ast::WebidlCompoundType::Function(f) => f,
_ => bail!("webidl type for function must be of function type"),
};
let skip = if uses_retptr(&binding.result.bindings) {
1
} else {
0
};
func.params
.iter()
.skip(skip)
.map(|param| match param {
ast::WebidlTypeRef::Id(_) => bail!("function arguments cannot be compound"),
ast::WebidlTypeRef::Scalar(s) => Ok(*s),
Expand Down Expand Up @@ -297,12 +277,11 @@ fn translate_incoming(
cx: &mut Context,
handle: &mut InstanceHandle,
bindings: &[ast::IncomingBindingExpression],
offset: u32,
args: &[Value],
) -> Result<Vec<RuntimeValue>, Error> {
let get = |expr: &ast::IncomingBindingExpression| match expr {
ast::IncomingBindingExpression::Get(g) => args
.get((g.idx - offset) as usize)
.get(g.idx as usize)
.ok_or_else(|| format_err!("argument index out of bounds: {}", g.idx)),
_ => bail!("unsupported incoming binding expr {:?}", expr),
};
Expand Down Expand Up @@ -389,7 +368,6 @@ fn translate_outgoing(
cx: &mut Context,
handle: &mut InstanceHandle,
bindings: &[ast::OutgoingBindingExpression],
retptr: Option<u32>,
args: &[RuntimeValue],
) -> Result<Vec<Value>, Error> {
let mut values = Vec::new();
Expand All @@ -408,25 +386,10 @@ fn translate_outgoing(
))
};

if retptr.is_some() {
assert!(args.is_empty());
}

let get = |idx: u32| match retptr {
Some(i) => {
let bytes = raw_memory()?;
let base = &bytes[(i + idx * 4) as usize..][..4];
Ok(RuntimeValue::I32(
((base[0] as i32) << 0)
| ((base[1] as i32) << 8)
| ((base[2] as i32) << 16)
| ((base[3] as i32) << 24),
))
}
None => args
.get(idx as usize)
let get = |idx: u32| {
args.get(idx as usize)
.cloned()
.ok_or_else(|| format_err!("argument index out of bounds: {}", idx)),
.ok_or_else(|| format_err!("argument index out of bounds: {}", idx))
};

for expr in bindings {
Expand Down Expand Up @@ -490,10 +453,3 @@ fn translate_outgoing(

Ok(values)
}

fn uses_retptr(outgoing: &[ast::OutgoingBindingExpression]) -> bool {
match outgoing.get(0) {
Some(ast::OutgoingBindingExpression::As(e)) => e.idx == u32::max_value(),
_ => false,
}
}

0 comments on commit 5cfd0b7

Please sign in to comment.