Skip to content

Commit

Permalink
Support the Tail Call Proposal
Browse files Browse the repository at this point in the history
This adds support for the Tail Call Proposal.
  • Loading branch information
CryZe committed Sep 16, 2024
1 parent 20c010d commit a8034bf
Show file tree
Hide file tree
Showing 11 changed files with 43 additions and 21 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

### Added

* Added support for the WebAssembly `Tail Call` proposal.
[#4111](https://github.com/rustwasm/wasm-bindgen/pull/4111)

* Add bindings for `RTCPeerConnection.setConfiguration(RTCConfiguration)` method.
[#4105](https://github.com/rustwasm/wasm-bindgen/pull/4105)

Expand Down Expand Up @@ -204,7 +207,7 @@ Released 2024-08-13

* Fix MDN links to static interface methods.
[#4010](https://github.com/rustwasm/wasm-bindgen/pull/4010)

* Fixed Deno support.
[#3990](https://github.com/rustwasm/wasm-bindgen/pull/3990)

Expand Down
2 changes: 1 addition & 1 deletion crates/cli-support/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tempfile = "3.0"
unicode-ident = "1.0.5"
walrus = "0.21"
walrus = "0.21.2"
wasm-bindgen-externref-xform = { path = '../externref-xform', version = '=0.2.93' }
wasm-bindgen-multi-value-xform = { path = '../multi-value-xform', version = '=0.2.93' }
wasm-bindgen-shared = { path = "../shared", version = '=0.2.93' }
Expand Down
12 changes: 12 additions & 0 deletions crates/cli-support/src/descriptors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,12 @@ impl WasmBindgenDescriptorsSection {
self.found = true;
}
}

fn visit_return_call(&mut self, instr: &walrus::ir::ReturnCall) {
if instr.func == self.wbindgen_describe_closure {
self.found = true;
}
}
}

struct UpdateDescribeClosure {
Expand All @@ -212,6 +218,12 @@ impl WasmBindgenDescriptorsSection {
call.func = self.replacement;
}
}

fn visit_return_call_mut(&mut self, instr: &mut walrus::ir::ReturnCall) {
if instr.func == self.wbindgen_describe_closure {
instr.func = self.replacement;
}
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ serde = { version = "1.0", features = ['derive'] }
serde_derive = "1.0"
serde_json = "1.0"
ureq = { version = "2.7", default-features = false, features = ["brotli", "gzip"] }
walrus = { version = "0.21", features = ['parallel'] }
walrus = { version = "0.21.2", features = ['parallel'] }
wasm-bindgen-cli-support = { path = "../cli-support", version = "=0.2.93" }
wasm-bindgen-shared = { path = "../shared", version = "=0.2.93" }

Expand Down
2 changes: 1 addition & 1 deletion crates/externref-xform/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ version = "0.2.93"

[dependencies]
anyhow = "1.0"
walrus = "0.21"
walrus = "0.21.2"
wasm-bindgen-wasm-conventions = { path = "../wasm-conventions", version = "=0.2.93" }

[dev-dependencies]
Expand Down
15 changes: 8 additions & 7 deletions crates/externref-xform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,18 +722,19 @@ impl Transform<'_> {
impl VisitorMut for Rewrite<'_, '_> {
fn start_instr_seq_mut(&mut self, seq: &mut InstrSeq) {
for i in (0..seq.instrs.len()).rev() {
let call = match &mut seq.instrs[i].0 {
Instr::Call(call) => call,
let func = match &mut seq.instrs[i].0 {
Instr::Call(Call { func }) => func,
Instr::ReturnCall(ReturnCall { func }) => func,
_ => continue,
};
let intrinsic = match self.xform.intrinsic_map.get(&call.func) {
let intrinsic = match self.xform.intrinsic_map.get(func) {
Some(f) => f,
None => {
// If this wasn't a call of an intrinsic, but it was a
// call of one of our old import functions then we
// switch the functions we're calling here.
if let Some(f) = self.xform.import_map.get(&call.func) {
call.func = *f;
if let Some(f) = self.xform.import_map.get(func) {
*func = *f;
}
continue;
}
Expand Down Expand Up @@ -776,8 +777,8 @@ impl Transform<'_> {
seq.instrs
.insert(i, (RefNull { ty }.into(), InstrLocId::default()));
}
Intrinsic::DropRef => call.func = self.heap_dealloc,
Intrinsic::CloneRef => call.func = self.clone_ref,
Intrinsic::DropRef => *func = self.heap_dealloc,
Intrinsic::CloneRef => *func = self.clone_ref,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/multi-value-xform/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ version = "0.2.93"

[dependencies]
anyhow = "1.0"
walrus = "0.21"
walrus = "0.21.2"
wasm-bindgen-wasm-conventions = { path = "../wasm-conventions", version = "=0.2.93" }

[dev-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion crates/threads-xform/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ version = "0.2.93"

[dependencies]
anyhow = "1.0"
walrus = "0.21"
walrus = "0.21.2"
wasm-bindgen-wasm-conventions = { path = "../wasm-conventions", version = "=0.2.93" }

[dev-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion crates/wasm-conventions/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ version = "0.2.93"

[dependencies]
leb128 = "0.2"
walrus = "0.21"
walrus = "0.21.2"
# Matching the version `walrus` depends on.
anyhow = "1.0"
log = "0.4"
Expand Down
2 changes: 1 addition & 1 deletion crates/wasm-interpreter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ version = "0.2.93"
[dependencies]
anyhow = "1.0"
log = "0.4"
walrus = "0.21"
walrus = "0.21.2"
wasm-bindgen-wasm-conventions = { path = "../wasm-conventions", version = "0.2.93" }

[dev-dependencies]
Expand Down
18 changes: 12 additions & 6 deletions crates/wasm-interpreter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,13 +338,14 @@ impl Frame<'_> {
stack.pop().unwrap();
}

Instr::Call(e) => {
Instr::Call(Call { func }) | Instr::ReturnCall(ReturnCall { func }) => {
let func = *func;
// If this function is calling the `__wbindgen_describe`
// function, which we've precomputed the id for, then
// it's telling us about the next `u32` element in the
// descriptor to return. We "call" the imported function
// here by directly inlining it.
if Some(e.func) == self.interp.describe_id {
if Some(func) == self.interp.describe_id {
let val = stack.pop().unwrap();
log::debug!("__wbindgen_describe({})", val);
self.interp.descriptor.push(val as u32);
Expand All @@ -354,7 +355,7 @@ impl Frame<'_> {
// slightly different signature. Note that we don't eval the
// previous arguments because they shouldn't have any side
// effects we're interested in.
} else if Some(e.func) == self.interp.describe_closure_id {
} else if Some(func) == self.interp.describe_closure_id {
let val = stack.pop().unwrap();
stack.pop();
stack.pop();
Expand All @@ -368,7 +369,7 @@ impl Frame<'_> {
if self
.module
.funcs
.get(e.func)
.get(func)
.name
.as_ref()
.is_some_and(|name| {
Expand All @@ -380,12 +381,17 @@ impl Frame<'_> {
return Ok(());
}

let ty = self.module.types.get(self.module.funcs.get(e.func).ty());
let ty = self.module.types.get(self.module.funcs.get(func).ty());
let args = (0..ty.params().len())
.map(|_| stack.pop().unwrap())
.collect::<Vec<_>>();

self.interp.call(e.func, self.module, &args);
self.interp.call(func, self.module, &args);
}

if let Instr::ReturnCall(_) = instr {
log::debug!("return_call");
self.done = true;
}
}

Expand Down

0 comments on commit a8034bf

Please sign in to comment.