Skip to content

Commit bf57bb4

Browse files
authored
Merge pull request #5 from dhil/wasmfx-merge
Merge with upstream
2 parents 28a4c28 + 3554aae commit bf57bb4

File tree

26 files changed

+630
-607
lines changed

26 files changed

+630
-607
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ bitflags = "2.3.3"
2626
heck = { version = "0.4", features = ["unicode"] }
2727
pulldown-cmark = { version = "0.9", default-features = false }
2828
clap = { version = "4.3.19", features = ["derive"] }
29-
env_logger = "0.10.0"
3029
indexmap = "2.0.0"
3130

3231
wasmparser = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "wasmfx-tools-1.201.0+rev.1" }
@@ -80,8 +79,8 @@ csharp-mono = ['csharp']
8079

8180
[dev-dependencies]
8281
heck = { workspace = true }
83-
wasmtime = { version = "17.0.0", features = ['component-model'] }
84-
wasmtime-wasi = { version = "17.0.0" }
82+
wasmtime = { version = "19.0.0", features = ['component-model'] }
83+
wasmtime-wasi = { version = "19.0.0" }
8584
test-artifacts = { path = 'crates/test-rust-wasm/artifacts' }
8685
wit-parser = { workspace = true }
8786
wasmparser = { workspace = true }

crates/c/src/lib.rs

Lines changed: 86 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ struct C {
2222
return_pointer_area_align: usize,
2323
names: Ns,
2424
needs_string: bool,
25+
needs_union_int32_float: bool,
26+
needs_union_float_int32: bool,
27+
needs_union_int64_double: bool,
28+
needs_union_double_int64: bool,
2529
prim_names: HashSet<String>,
2630
world: String,
2731
sizes: SizeAlign,
@@ -331,7 +335,7 @@ impl WorldGenerator for C {
331335
self.src.h_helpers,
332336
"
333337
// Transfers ownership of `s` into the string `ret`
334-
void {snake}_string_set({snake}_string_t *ret, {c_string_ty} *s);
338+
void {snake}_string_set({snake}_string_t *ret, const {c_string_ty} *s);
335339
336340
// Creates a copy of the input nul-terminate string `s` and
337341
// stores it into the component model string `ret`.
@@ -345,14 +349,14 @@ impl WorldGenerator for C {
345349
uwrite!(
346350
self.src.c_helpers,
347351
"
348-
void {snake}_string_set({snake}_string_t *ret, {c_string_ty} *s) {{
352+
void {snake}_string_set({snake}_string_t *ret, const {c_string_ty} *s) {{
349353
ret->ptr = ({ty}*) s;
350354
ret->len = {strlen};
351355
}}
352356
353357
void {snake}_string_dup({snake}_string_t *ret, const {c_string_ty} *s) {{
354358
ret->len = {strlen};
355-
ret->ptr = cabi_realloc(NULL, 0, {size}, ret->len * {size});
359+
ret->ptr = ({ty}*) cabi_realloc(NULL, 0, {size}, ret->len * {size});
356360
memcpy(ret->ptr, s, ret->len * {size});
357361
}}
358362
@@ -366,6 +370,30 @@ impl WorldGenerator for C {
366370
",
367371
);
368372
}
373+
if self.needs_union_int32_float {
374+
uwriteln!(
375+
self.src.c_helpers,
376+
"\nunion int32_float {{ int32_t a; float b; }};"
377+
);
378+
}
379+
if self.needs_union_float_int32 {
380+
uwriteln!(
381+
self.src.c_helpers,
382+
"\nunion float_int32 {{ float a; int32_t b; }};"
383+
);
384+
}
385+
if self.needs_union_int64_double {
386+
uwriteln!(
387+
self.src.c_helpers,
388+
"\nunion int64_double {{ int64_t a; double b; }};"
389+
);
390+
}
391+
if self.needs_union_double_int64 {
392+
uwriteln!(
393+
self.src.c_helpers,
394+
"\nunion double_int64 {{ double a; int64_t b; }};"
395+
);
396+
}
369397
let version = env!("CARGO_PKG_VERSION");
370398
let mut h_str = wit_bindgen_core::Source::default();
371399

@@ -570,6 +598,51 @@ impl C {
570598
self.type_names.retain(|k, _| live_import_types.contains(k));
571599
self.resources.retain(|k, _| live_import_types.contains(k));
572600
}
601+
602+
fn perform_cast(&mut self, op: &str, cast: &Bitcast) -> String {
603+
match cast {
604+
Bitcast::I32ToF32 | Bitcast::I64ToF32 => {
605+
self.needs_union_int32_float = true;
606+
format!("((union int32_float){{ (int32_t) {} }}).b", op)
607+
}
608+
Bitcast::F32ToI32 | Bitcast::F32ToI64 => {
609+
self.needs_union_float_int32 = true;
610+
format!("((union float_int32){{ {} }}).b", op)
611+
}
612+
Bitcast::I64ToF64 => {
613+
self.needs_union_int64_double = true;
614+
format!("((union int64_double){{ (int64_t) {} }}).b", op)
615+
}
616+
Bitcast::F64ToI64 => {
617+
self.needs_union_double_int64 = true;
618+
format!("((union double_int64){{ {} }}).b", op)
619+
}
620+
Bitcast::I32ToI64 | Bitcast::LToI64 | Bitcast::PToP64 => {
621+
format!("(int64_t) {}", op)
622+
}
623+
Bitcast::I64ToI32 | Bitcast::I64ToL => {
624+
format!("(int32_t) {}", op)
625+
}
626+
// P64 is currently represented as int64_t, so no conversion is needed.
627+
Bitcast::I64ToP64 | Bitcast::P64ToI64 => {
628+
format!("{}", op)
629+
}
630+
Bitcast::P64ToP | Bitcast::I32ToP | Bitcast::LToP => {
631+
format!("(uint8_t *) {}", op)
632+
}
633+
634+
// Cast to uintptr_t to avoid implicit pointer-to-int conversions.
635+
Bitcast::PToI32 | Bitcast::PToL => format!("(uintptr_t) {}", op),
636+
637+
Bitcast::I32ToL | Bitcast::LToI32 | Bitcast::None => op.to_string(),
638+
639+
Bitcast::Sequence(sequence) => {
640+
let [first, second] = &**sequence;
641+
let inner = self.perform_cast(op, first);
642+
self.perform_cast(&inner, second)
643+
}
644+
}
645+
}
573646
}
574647

575648
pub fn imported_types_used_by_exported_interfaces(
@@ -2068,7 +2141,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
20682141
fn load_ext(&mut self, ty: &str, offset: i32, operands: &[String], results: &mut Vec<String>) {
20692142
self.load(ty, offset, operands, results);
20702143
let result = results.pop().unwrap();
2071-
results.push(format!("(int32_t) ({})", result));
2144+
results.push(format!("(int32_t) {}", result));
20722145
}
20732146

20742147
fn store(&mut self, ty: &str, offset: i32, operands: &[String]) {
@@ -2208,7 +2281,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
22082281

22092282
Instruction::Bitcasts { casts } => {
22102283
for (cast, op) in casts.iter().zip(operands) {
2211-
let op = perform_cast(op, cast);
2284+
let op = self.gen.gen.perform_cast(op, cast);
22122285
results.push(op);
22132286
}
22142287
}
@@ -2223,11 +2296,12 @@ impl Bindgen for FunctionBindgen<'_, '_> {
22232296
results.push(format!("({}).{}", op, to_c_ident(&f.name)));
22242297
}
22252298
}
2226-
Instruction::RecordLift { ty, .. } => {
2299+
Instruction::RecordLift { ty, record, .. } => {
22272300
let name = self.gen.gen.type_name(&Type::Id(*ty));
22282301
let mut result = format!("({}) {{\n", name);
2229-
for op in operands {
2230-
uwriteln!(result, "{},", op);
2302+
for (field, op) in record.fields.iter().zip(operands.iter()) {
2303+
let field_ty = self.gen.gen.type_name(&field.ty);
2304+
uwriteln!(result, "({}) {},", field_ty, op);
22312305
}
22322306
result.push_str("}");
22332307
results.push(result);
@@ -2239,11 +2313,12 @@ impl Bindgen for FunctionBindgen<'_, '_> {
22392313
results.push(format!("({}).f{}", op, i));
22402314
}
22412315
}
2242-
Instruction::TupleLift { ty, .. } => {
2316+
Instruction::TupleLift { ty, tuple, .. } => {
22432317
let name = self.gen.gen.type_name(&Type::Id(*ty));
22442318
let mut result = format!("({}) {{\n", name);
2245-
for op in operands {
2246-
uwriteln!(result, "{},", op);
2319+
for (ty, op) in tuple.types.iter().zip(operands.iter()) {
2320+
let ty = self.gen.gen.type_name(&ty);
2321+
uwriteln!(result, "({}) {},", ty, op);
22472322
}
22482323
result.push_str("}");
22492324
results.push(result);
@@ -2943,46 +3018,6 @@ impl Bindgen for FunctionBindgen<'_, '_> {
29433018
}
29443019
}
29453020

2946-
fn perform_cast(op: &str, cast: &Bitcast) -> String {
2947-
match cast {
2948-
Bitcast::I32ToF32 | Bitcast::I64ToF32 => {
2949-
format!("((union {{ int32_t a; float b; }}){{ {} }}).b", op)
2950-
}
2951-
Bitcast::F32ToI32 | Bitcast::F32ToI64 => {
2952-
format!("((union {{ float a; int32_t b; }}){{ {} }}).b", op)
2953-
}
2954-
Bitcast::I64ToF64 => {
2955-
format!("((union {{ int64_t a; double b; }}){{ {} }}).b", op)
2956-
}
2957-
Bitcast::F64ToI64 => {
2958-
format!("((union {{ double a; int64_t b; }}){{ {} }}).b", op)
2959-
}
2960-
Bitcast::I32ToI64 | Bitcast::LToI64 | Bitcast::PToP64 => {
2961-
format!("(int64_t) {}", op)
2962-
}
2963-
Bitcast::I64ToI32 | Bitcast::I64ToL => {
2964-
format!("(int32_t) {}", op)
2965-
}
2966-
// P64 is currently represented as int64_t, so no conversion is needed.
2967-
Bitcast::I64ToP64 | Bitcast::P64ToI64 => {
2968-
format!("{}", op)
2969-
}
2970-
Bitcast::P64ToP | Bitcast::I32ToP | Bitcast::LToP => {
2971-
format!("(uint8_t *) {}", op)
2972-
}
2973-
2974-
// Cast to uintptr_t to avoid implicit pointer-to-int conversions.
2975-
Bitcast::PToI32 | Bitcast::PToL => format!("(uintptr_t) {}", op),
2976-
2977-
Bitcast::I32ToL | Bitcast::LToI32 | Bitcast::None => op.to_string(),
2978-
2979-
Bitcast::Sequence(sequence) => {
2980-
let [first, second] = &**sequence;
2981-
perform_cast(&perform_cast(op, first), second)
2982-
}
2983-
}
2984-
}
2985-
29863021
#[derive(Default, Clone, Copy)]
29873022
enum SourceType {
29883023
#[default]

crates/c/tests/codegen.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ fn verify(dir: &Path, name: &str) {
6161
dir.to_str().unwrap(),
6262
"-Wall",
6363
"-Wextra",
64+
"-Wc++-compat",
6465
"-Werror",
6566
"-Wno-unused-parameter",
6667
"-c",

crates/csharp/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ impl WorldGenerator for CSharp {
478478
/* of WASI libc prevent us doing so. */
479479
/* See https://github.com/bytecodealliance/wit-bindgen/issues/777 */
480480
/* and https://github.com/WebAssembly/wasi-libc/issues/452 */
481-
/* The component model `start` function might be an alternative to this depending on whether it
481+
/* The component model `start` function might be an alternative to this depending on whether it */
482482
/* has the same constraints as `cabi_realloc` */
483483
__attribute__((__weak__, __export_name__("cabi_realloc")))
484484
void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) {
@@ -586,7 +586,7 @@ impl WorldGenerator for CSharp {
586586
// temporarily add this attribute until it is available in dotnet 9
587587
namespace System.Runtime.InteropServices
588588
{
589-
public class WasmImportLinkageAttribute : Attribute {}
589+
internal partial class WasmImportLinkageAttribute : Attribute {}
590590
}
591591
"#,
592592
);

crates/guest-rust/Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ Used when compiling Rust programs to the component model.
1313

1414
[dependencies]
1515
wit-bindgen-rust-macro = { path = "./macro", optional = true, version = "0.22.0" }
16-
wit-bindgen-rt = { path = "./rt", optional = true, version = "0.22.0" }
17-
bitflags = { workspace = true }
16+
wit-bindgen-rt = { path = "./rt", version = "0.22.0", features = ["bitflags"] }
1817

1918
[features]
2019
default = ["macros", "realloc"]
2120
macros = ["dep:wit-bindgen-rust-macro"]
22-
realloc = ["dep:wit-bindgen-rt"]
21+
realloc = []

crates/guest-rust/macro/src/lib.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ impl Parse for Config {
101101
Opt::TypeSectionSuffix(suffix) => {
102102
opts.type_section_suffix = Some(suffix.value());
103103
}
104-
Opt::RunCtorsOnceWorkaround(enable) => {
105-
opts.run_ctors_once_workaround = enable.value();
104+
Opt::DisableRunCtorsOnceWorkaround(enable) => {
105+
opts.disable_run_ctors_once_workaround = enable.value();
106106
}
107107
Opt::DefaultBindingsModule(enable) => {
108108
opts.default_bindings_module = Some(enable.value());
@@ -227,7 +227,7 @@ mod kw {
227227
syn::custom_keyword!(additional_derives);
228228
syn::custom_keyword!(with);
229229
syn::custom_keyword!(type_section_suffix);
230-
syn::custom_keyword!(run_ctors_once_workaround);
230+
syn::custom_keyword!(disable_run_ctors_once_workaround);
231231
syn::custom_keyword!(default_bindings_module);
232232
syn::custom_keyword!(export_macro_name);
233233
syn::custom_keyword!(pub_export_macro);
@@ -276,7 +276,7 @@ enum Opt {
276276
AdditionalDerives(Vec<syn::Path>),
277277
With(HashMap<String, String>),
278278
TypeSectionSuffix(syn::LitStr),
279-
RunCtorsOnceWorkaround(syn::LitBool),
279+
DisableRunCtorsOnceWorkaround(syn::LitBool),
280280
DefaultBindingsModule(syn::LitStr),
281281
ExportMacroName(syn::LitStr),
282282
PubExportMacro(syn::LitBool),
@@ -382,10 +382,10 @@ impl Parse for Opt {
382382
input.parse::<kw::type_section_suffix>()?;
383383
input.parse::<Token![:]>()?;
384384
Ok(Opt::TypeSectionSuffix(input.parse()?))
385-
} else if l.peek(kw::run_ctors_once_workaround) {
386-
input.parse::<kw::run_ctors_once_workaround>()?;
385+
} else if l.peek(kw::disable_run_ctors_once_workaround) {
386+
input.parse::<kw::disable_run_ctors_once_workaround>()?;
387387
input.parse::<Token![:]>()?;
388-
Ok(Opt::RunCtorsOnceWorkaround(input.parse()?))
388+
Ok(Opt::DisableRunCtorsOnceWorkaround(input.parse()?))
389389
} else if l.peek(kw::default_bindings_module) {
390390
input.parse::<kw::default_bindings_module>()?;
391391
input.parse::<Token![:]>()?;

crates/guest-rust/rt/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@ homepage = 'https://github.com/bytecodealliance/wit-bindgen'
88
description = """
99
Runtime support for the `wit-bindgen` crate
1010
"""
11+
12+
[dependencies]
13+
# Optionally re-export the version of bitflags used by wit-bindgen.
14+
bitflags = { workspace = true, optional = true }

crates/guest-rust/rt/src/lib.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22

33
extern crate alloc;
44

5+
// Re-export `bitflags` so that we can reference it from macros.
6+
#[cfg(feature = "bitflags")]
7+
#[doc(hidden)]
8+
pub use bitflags;
9+
510
/// For more information about this see `./ci/rebuild-libcabi-realloc.sh`.
11+
#[cfg(not(target_env = "p2"))]
612
mod cabi_realloc;
713

814
/// This function is called from generated bindings and will be deleted by
@@ -13,7 +19,7 @@ mod cabi_realloc;
1319
///
1420
/// For more information about this see `./ci/rebuild-libcabi-realloc.sh`.
1521
pub fn maybe_link_cabi_realloc() {
16-
#[cfg(target_family = "wasm")]
22+
#[cfg(all(target_family = "wasm", not(target_env = "p2")))]
1723
{
1824
extern "C" {
1925
fn cabi_realloc(
@@ -44,6 +50,7 @@ pub fn maybe_link_cabi_realloc() {
4450
/// `cabi_realloc` module above. It's otherwise never explicitly called.
4551
///
4652
/// For more information about this see `./ci/rebuild-libcabi-realloc.sh`.
53+
#[cfg(not(target_env = "p2"))]
4754
pub unsafe fn cabi_realloc(
4855
old_ptr: *mut u8,
4956
old_len: usize,
@@ -79,3 +86,29 @@ pub unsafe fn cabi_realloc(
7986
}
8087
return ptr;
8188
}
89+
90+
/// Provide a hook for generated export functions to run static constructors at
91+
/// most once.
92+
///
93+
/// wit-bindgen-rust generates a call to this function at the start of all
94+
/// component export functions. Importantly, it is not called as part of
95+
/// `cabi_realloc`, which is a *core* export func, but should not execute ctors.
96+
#[cfg(target_arch = "wasm32")]
97+
pub fn run_ctors_once() {
98+
static mut RUN: bool = false;
99+
unsafe {
100+
if !RUN {
101+
// This function is synthesized by `wasm-ld` to run all static
102+
// constructors. wasm-ld will either provide an implementation
103+
// of this symbol, or synthesize a wrapper around each
104+
// exported function to (unconditionally) run ctors. By using
105+
// this function, the linked module is opting into "manually"
106+
// running ctors.
107+
extern "C" {
108+
fn __wasm_call_ctors();
109+
}
110+
__wasm_call_ctors();
111+
RUN = true;
112+
}
113+
}
114+
}

0 commit comments

Comments
 (0)