Skip to content

Commit 98772fb

Browse files
authored
Update to the new async abi (#1302)
* Update to the new async abi This commit refactors the C/Rust bindings generators to handle the new async import ABI which allows up to 4 flat parameters instead of always having all parameters being indirect. Additionally the return pointer is omitted in the ABI if there are no return values. * Update wasm-tools dependencies
1 parent b98f2e8 commit 98772fb

File tree

18 files changed

+713
-416
lines changed

18 files changed

+713
-416
lines changed

Cargo.lock

Lines changed: 89 additions & 83 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ prettyplease = "0.2.20"
3131
syn = { version = "2.0.89", features = ["printing"] }
3232
futures = "0.3.31"
3333

34-
wat = "1.230.0"
35-
wasmparser = "0.230.0"
36-
wasm-encoder = "0.230.0"
37-
wasm-metadata = { version = "0.230.0", default-features = false }
38-
wit-parser = "0.230.0"
39-
wit-component = "0.230.0"
40-
wasm-compose = "0.230.0"
34+
wat = "1.232.0"
35+
wasmparser = "0.232.0"
36+
wasm-encoder = "0.232.0"
37+
wasm-metadata = { version = "0.232.0", default-features = false }
38+
wit-parser = "0.232.0"
39+
wit-component = "0.232.0"
40+
wasm-compose = "0.232.0"
4141

4242
wit-bindgen-core = { path = 'crates/core', version = '0.42.1' }
4343
wit-bindgen-c = { path = 'crates/c', version = '0.42.1' }

crates/c/src/lib.rs

Lines changed: 107 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use indexmap::IndexSet;
66
use std::collections::{HashMap, HashSet};
77
use std::fmt::Write;
88
use std::mem;
9-
use wit_bindgen_core::abi::{self, AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmType};
9+
use wit_bindgen_core::abi::{
10+
self, AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmSignature, WasmType,
11+
};
1012
use wit_bindgen_core::{
1113
dealias, uwrite, uwriteln, wit_parser::*, AnonymousTypeGenerator, AsyncFilterSet, Direction,
1214
Files, InterfaceGenerator as _, Ns, WorldGenerator,
@@ -139,12 +141,13 @@ impl Opts {
139141
}
140142
}
141143

142-
#[derive(Debug, Default)]
144+
#[derive(Clone, Debug, Default)]
143145
struct Return {
144146
scalar: Option<Scalar>,
145147
retptrs: Vec<Type>,
146148
}
147149

150+
#[derive(Clone)]
148151
struct CSig {
149152
name: String,
150153
sig: String,
@@ -153,7 +156,7 @@ struct CSig {
153156
retptrs: Vec<String>,
154157
}
155158

156-
#[derive(Debug)]
159+
#[derive(Clone, Debug)]
157160
enum Scalar {
158161
Void,
159162
OptionBool(Type),
@@ -1949,13 +1952,13 @@ impl InterfaceGenerator<'_> {
19491952
// Print the public facing signature into the header, and since that's
19501953
// what we are defining also print it into the C file.
19511954
self.src.h_fns("extern ");
1952-
let c_sig = self.print_sig(interface_name, func, async_);
1955+
let c_sig = self.print_sig(interface_name, func, &sig, async_);
19531956
self.src.c_adapters("\n");
19541957
self.src.c_adapters(&c_sig.sig);
19551958
self.src.c_adapters(" {\n");
19561959

19571960
if async_ {
1958-
self.import_body_async(func, c_sig, &import_name);
1961+
self.import_body_async(func, c_sig, &sig, &import_name);
19591962
} else {
19601963
self.import_body_sync(func, c_sig, &import_name);
19611964
}
@@ -1993,7 +1996,6 @@ impl InterfaceGenerator<'_> {
19931996

19941997
let mut f = FunctionBindgen::new(self, c_sig, &import_name);
19951998
for (pointer, param) in f.sig.params.iter() {
1996-
f.locals.insert(&param).unwrap();
19971999
if *pointer {
19982000
f.params.push(format!("*{}", param));
19992001
} else {
@@ -2034,19 +2036,31 @@ impl InterfaceGenerator<'_> {
20342036
self.src.c_adapters(&String::from(src));
20352037
}
20362038

2037-
fn import_body_async(&mut self, func: &Function, sig: CSig, import_name: &str) {
2038-
let params = match &func.params[..] {
2039-
[] => "NULL".to_string(),
2040-
_ => format!("(uint8_t*) {}", sig.params[0].1),
2041-
};
2042-
let results = match &func.result {
2043-
None => "NULL".to_string(),
2044-
Some(_) => format!("(uint8_t*) {}", sig.params.last().unwrap().1),
2045-
};
2046-
2039+
fn import_body_async(
2040+
&mut self,
2041+
func: &Function,
2042+
c_sig: CSig,
2043+
wasm_sig: &WasmSignature,
2044+
import_name: &str,
2045+
) {
2046+
let mut params = Vec::new();
2047+
if wasm_sig.indirect_params {
2048+
params.push(format!("(uint8_t*) {}", c_sig.params[0].1));
2049+
} else {
2050+
let mut f = FunctionBindgen::new(self, c_sig.clone(), "INVALID");
2051+
for (i, (_, ty)) in func.params.iter().enumerate() {
2052+
let param = &c_sig.params[i].1;
2053+
params.extend(abi::lower_flat(f.gen.resolve, &mut f, param.clone(), ty));
2054+
}
2055+
f.gen.src.c_adapters.push_str(&f.src);
2056+
}
2057+
if func.result.is_some() {
2058+
params.push(format!("(uint8_t*) {}", c_sig.params.last().unwrap().1));
2059+
}
20472060
uwriteln!(
20482061
self.src.c_adapters,
2049-
"return {import_name}({params}, {results});"
2062+
"return {import_name}({});",
2063+
params.join(", "),
20502064
);
20512065
}
20522066

@@ -2064,11 +2078,7 @@ impl InterfaceGenerator<'_> {
20642078
(AbiVariant::GuestExport, "")
20652079
};
20662080

2067-
let mut sig = self.resolve.wasm_signature(variant, func);
2068-
if async_ {
2069-
assert_eq!(sig.results, [WasmType::Pointer]);
2070-
sig.results[0] = WasmType::I32;
2071-
}
2081+
let sig = self.resolve.wasm_signature(variant, func);
20722082

20732083
self.src.c_fns("\n");
20742084

@@ -2077,7 +2087,7 @@ impl InterfaceGenerator<'_> {
20772087

20782088
// Print the actual header for this function into the header file, and
20792089
// it's what we'll be calling.
2080-
let h_sig = self.print_sig(interface_name, func, async_);
2090+
let h_sig = self.print_sig(interface_name, func, &sig, async_);
20812091

20822092
// Generate, in the C source file, the raw wasm signature that has the
20832093
// canonical ABI.
@@ -2220,6 +2230,7 @@ void {name}_return({return_ty}) {{
22202230
&mut self,
22212231
interface_name: Option<&WorldKey>,
22222232
func: &Function,
2233+
sig: &WasmSignature,
22232234
async_: bool,
22242235
) -> CSig {
22252236
let name = self.c_func_name(interface_name, func);
@@ -2259,50 +2270,10 @@ void {name}_return({return_ty}) {{
22592270
self.src.h_fns(" ");
22602271
self.src.h_fns(&name);
22612272
self.src.h_fns("(");
2262-
let mut params = Vec::new();
2273+
let params;
22632274
let mut retptrs = Vec::new();
22642275
if async_ && self.in_import {
2265-
let mut printed = false;
2266-
match &func.params[..] {
2267-
[] => {}
2268-
[(_name, ty)] => {
2269-
printed = true;
2270-
let name = "arg".to_string();
2271-
self.print_ty(SourceType::HFns, ty);
2272-
self.src.h_fns(" *");
2273-
self.src.h_fns(&name);
2274-
params.push((true, name));
2275-
}
2276-
multiple => {
2277-
printed = true;
2278-
let names = multiple
2279-
.iter()
2280-
.map(|(name, ty)| (to_c_ident(name), self.gen.type_name(ty)))
2281-
.collect::<Vec<_>>();
2282-
uwriteln!(self.src.h_defs, "typedef struct {name}_args {{");
2283-
for (name, ty) in names {
2284-
uwriteln!(self.src.h_defs, "{ty} {name};");
2285-
}
2286-
uwriteln!(self.src.h_defs, "}} {name}_args_t;");
2287-
uwrite!(self.src.h_fns, "{name}_args_t *args");
2288-
params.push((true, "args".to_string()));
2289-
}
2290-
}
2291-
if let Some(ty) = &func.result {
2292-
if printed {
2293-
self.src.h_fns(", ");
2294-
} else {
2295-
printed = true;
2296-
}
2297-
let name = "result".to_string();
2298-
self.print_ty(SourceType::HFns, ty);
2299-
self.src.h_fns(" *");
2300-
self.src.h_fns(&name);
2301-
params.push((true, name));
2302-
}
2303-
if !printed {
2304-
self.src.h_fns("void");
2305-
}
2276+
params = self.print_sig_async_import_params(&name, func, sig);
23062277
} else if async_ && !self.in_import {
23072278
params = self.print_sig_params(func);
23082279
} else {
@@ -2388,6 +2359,72 @@ void {name}_return({return_ty}) {{
23882359
params
23892360
}
23902361

2362+
fn print_sig_async_import_params(
2363+
&mut self,
2364+
c_func_name: &str,
2365+
func: &Function,
2366+
sig: &WasmSignature,
2367+
) -> Vec<(bool, String)> {
2368+
let mut params = Vec::new();
2369+
let mut printed = false;
2370+
if sig.indirect_params {
2371+
match &func.params[..] {
2372+
[] => {}
2373+
[(_name, ty)] => {
2374+
printed = true;
2375+
let name = "arg".to_string();
2376+
self.print_ty(SourceType::HFns, ty);
2377+
self.src.h_fns(" *");
2378+
self.src.h_fns(&name);
2379+
params.push((true, name));
2380+
}
2381+
multiple => {
2382+
printed = true;
2383+
let names = multiple
2384+
.iter()
2385+
.map(|(name, ty)| (to_c_ident(name), self.gen.type_name(ty)))
2386+
.collect::<Vec<_>>();
2387+
uwriteln!(self.src.h_defs, "typedef struct {c_func_name}_args {{");
2388+
for (name, ty) in names {
2389+
uwriteln!(self.src.h_defs, "{ty} {name};");
2390+
}
2391+
uwriteln!(self.src.h_defs, "}} {c_func_name}_args_t;");
2392+
uwrite!(self.src.h_fns, "{c_func_name}_args_t *args");
2393+
params.push((true, "args".to_string()));
2394+
}
2395+
}
2396+
} else {
2397+
for (name, ty) in func.params.iter() {
2398+
let name = to_c_ident(name);
2399+
if printed {
2400+
self.src.h_fns(", ");
2401+
} else {
2402+
printed = true;
2403+
}
2404+
self.print_ty(SourceType::HFns, ty);
2405+
self.src.h_fns(" ");
2406+
self.src.h_fns(&name);
2407+
params.push((false, name));
2408+
}
2409+
}
2410+
if let Some(ty) = &func.result {
2411+
if printed {
2412+
self.src.h_fns(", ");
2413+
} else {
2414+
printed = true;
2415+
}
2416+
let name = "result".to_string();
2417+
self.print_ty(SourceType::HFns, ty);
2418+
self.src.h_fns(" *");
2419+
self.src.h_fns(&name);
2420+
params.push((true, name));
2421+
}
2422+
if !printed {
2423+
self.src.h_fns("void");
2424+
}
2425+
params
2426+
}
2427+
23912428
fn classify_ret(&mut self, func: &Function) -> Return {
23922429
let mut ret = Return::default();
23932430
match &func.result {
@@ -2768,10 +2805,14 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
27682805
sig: CSig,
27692806
func_to_call: &'a str,
27702807
) -> FunctionBindgen<'a, 'b> {
2808+
let mut locals = Ns::default();
2809+
for (_, name) in sig.params.iter() {
2810+
locals.insert(name).unwrap();
2811+
}
27712812
FunctionBindgen {
27722813
gen,
27732814
sig,
2774-
locals: Default::default(),
2815+
locals,
27752816
src: Default::default(),
27762817
func_to_call,
27772818
block_storage: Vec::new(),

0 commit comments

Comments
 (0)