Skip to content

Commit

Permalink
Move cabi_realloc to a wit-bindgen-rt crate (#876)
Browse files Browse the repository at this point in the history
* Move `cabi_realloc` to a `wit-bindgen-rt` crate

This commit extracts out a `wit-bindgen-rt` crate which unconditionally
provides the `cabi_realloc` function. This'll exist for `cargo
component` to add a dependency on and otherwise the `wit-bindgen` crate
isn't actually need at runtime at all.

* Remove realloc feature gate

* Add runtime to publish script

* Remove realloc feature guard in build script
  • Loading branch information
alexcrichton authored Mar 1, 2024
1 parent 29c1079 commit 4c7f1cf
Show file tree
Hide file tree
Showing 16 changed files with 120 additions and 96 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,12 @@ jobs:
- run: cargo build --no-default-features --features csharp
- run: cargo build --no-default-features --features markdown

# Feature combos of the `wit-bindgen` crate
- run: cargo build --target wasm32-wasi -p wit-bindgen --no-default-features
- run: cargo build --target wasm32-wasi -p wit-bindgen --no-default-features --features realloc
- run: cargo build --target wasm32-wasi -p wit-bindgen --no-default-features --features macros
- run: cargo build --target wasm32-wasi -p wit-bindgen --no-default-features --features macros,realloc

# Verity that documentation can be generated for the rust bindings crate.
- run: cargo doc -p wit-bindgen --no-deps
env:
Expand Down
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions ci/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const CRATES_TO_PUBLISH: &[&str] = &[
"wit-bindgen-teavm-java",
"wit-bindgen-markdown",
"wit-bindgen-rust-macro",
"wit-bindgen-rt",
"wit-bindgen",
"wit-bindgen-cli",
];
Expand Down
22 changes: 11 additions & 11 deletions ci/rebuild-libcabi-realloc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ version=$(grep '^version =' ./Cargo.toml | sed 's/.*"\(.*\)"/\1/' | sed 's/\./_/

sym=cabi_realloc_wit_bindgen_$version

cat >./crates/guest-rust/src/cabi_realloc.rs <<-EOF
cat >./crates/guest-rust/rt/src/cabi_realloc.rs <<-EOF
// This file is generated by $0
#[no_mangle]
Expand All @@ -53,11 +53,11 @@ pub unsafe extern "C" fn $sym(
align: usize,
new_len: usize,
) -> *mut u8 {
crate::rt::cabi_realloc(old_ptr, old_len, align, new_len)
crate::cabi_realloc(old_ptr, old_len, align, new_len)
}
EOF

cat >./crates/guest-rust/src/cabi_realloc.c <<-EOF
cat >./crates/guest-rust/rt/src/cabi_realloc.c <<-EOF
// This file is generated by $0
#include <stdint.h>
Expand All @@ -70,16 +70,16 @@ void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) {
}
EOF

rm -f crates/guest-rust/src/cabi_realloc.o
$WASI_SDK_PATH/bin/clang crates/guest-rust/src/cabi_realloc.c \
-O -c -o crates/guest-rust/src/cabi_realloc.o
rm -f crates/guest-rust/rt/src/cabi_realloc.o
$WASI_SDK_PATH/bin/clang crates/guest-rust/rt/src/cabi_realloc.c \
-O -c -o crates/guest-rust/rt/src/cabi_realloc.o

# Remove the `producers` section. This appears to differ whether the host for
# clang is either macOS or Linux. Not needed here anyway, so discard it to help
# either host produce the same object.
wasm-tools strip -d producers ./crates/guest-rust/src/cabi_realloc.o \
-o ./crates/guest-rust/src/cabi_realloc.o
wasm-tools strip -d producers ./crates/guest-rust/rt/src/cabi_realloc.o \
-o ./crates/guest-rust/rt/src/cabi_realloc.o

rm -f crates/guest-rust/src/libwit_bindgen_cabi_realloc.a
$WASI_SDK_PATH/bin/llvm-ar crus crates/guest-rust/src/libwit_bindgen_cabi_realloc.a \
crates/guest-rust/src/cabi_realloc.o
rm -f crates/guest-rust/rt/src/libwit_bindgen_cabi_realloc.a
$WASI_SDK_PATH/bin/llvm-ar crus crates/guest-rust/rt/src/libwit_bindgen_cabi_realloc.a \
crates/guest-rust/rt/src/cabi_realloc.o
7 changes: 4 additions & 3 deletions crates/guest-rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ Used when compiling Rust programs to the component model.
"""

[dependencies]
wit-bindgen-rust-macro = { path = "../rust-macro", optional = true, version = "0.20.0" }
wit-bindgen-rust-macro = { path = "./macro", optional = true, version = "0.20.0" }
wit-bindgen-rt = { path = "./rt", optional = true, version = "0.20.0" }
bitflags = { workspace = true }

[features]
default = ["macros", "realloc"]
macros = ["wit-bindgen-rust-macro"]
realloc = []
macros = ["dep:wit-bindgen-rust-macro"]
realloc = ["dep:wit-bindgen-rt"]
File renamed without changes.
File renamed without changes.
File renamed without changes.
10 changes: 10 additions & 0 deletions crates/guest-rust/rt/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "wit-bindgen-rt"
version.workspace = true
edition.workspace = true
repository = 'https://github.com/bytecodealliance/wit-bindgen'
license = "Apache-2.0 WITH LLVM-exception"
homepage = 'https://github.com/bytecodealliance/wit-bindgen'
description = """
Runtime support for the `wit-bindgen` crate
"""
4 changes: 0 additions & 4 deletions crates/guest-rust/build.rs → crates/guest-rust/rt/build.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
fn main() {
if !cfg!(feature = "realloc") {
return;
}

let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap_or(String::new());
let target_family = std::env::var("CARGO_CFG_TARGET_FAMILY").unwrap_or(String::new());

Expand Down
File renamed without changes.
Binary file added crates/guest-rust/rt/src/cabi_realloc.o
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ pub unsafe extern "C" fn cabi_realloc_wit_bindgen_0_20_0(
align: usize,
new_len: usize,
) -> *mut u8 {
crate::rt::cabi_realloc(old_ptr, old_len, align, new_len)
crate::cabi_realloc(old_ptr, old_len, align, new_len)
}
79 changes: 79 additions & 0 deletions crates/guest-rust/rt/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
extern crate alloc;

/// For more information about this see `./ci/rebuild-libcabi-realloc.sh`.
mod cabi_realloc;

/// This function is called from generated bindings and will be deleted by
/// the linker. The purpose of this function is to force a reference to the
/// symbol `cabi_realloc` to make its way through to the final linker
/// command line. That way `wasm-ld` will pick it up, see it needs to be
/// exported, and then export it.
///
/// For more information about this see `./ci/rebuild-libcabi-realloc.sh`.
pub fn maybe_link_cabi_realloc() {
#[cfg(target_family = "wasm")]
{
extern "C" {
fn cabi_realloc(
old_ptr: *mut u8,
old_len: usize,
align: usize,
new_len: usize,
) -> *mut u8;
}
// Force the `cabi_realloc` symbol to be referenced from here. This
// is done with a `#[used]` Rust `static` to ensure that this
// reference makes it all the way to the linker before it's
// considered for garbage collection. When the linker sees it it'll
// remove this `static` here (due to it not actually being needed)
// but the linker will have at that point seen the `cabi_realloc`
// symbol and it should get exported.
#[used]
static _NAME_DOES_NOT_MATTER: unsafe extern "C" fn(
*mut u8,
usize,
usize,
usize,
) -> *mut u8 = cabi_realloc;
}
}

/// NB: this function is called by a generated function in the
/// `cabi_realloc` module above. It's otherwise never explicitly called.
///
/// For more information about this see `./ci/rebuild-libcabi-realloc.sh`.
pub unsafe fn cabi_realloc(
old_ptr: *mut u8,
old_len: usize,
align: usize,
new_len: usize,
) -> *mut u8 {
use self::alloc::alloc::{self, Layout};

let layout;
let ptr = if old_len == 0 {
if new_len == 0 {
return align as *mut u8;
}
layout = Layout::from_size_align_unchecked(new_len, align);
alloc::alloc(layout)
} else {
debug_assert_ne!(new_len, 0, "non-zero old_len requires non-zero new_len!");
layout = Layout::from_size_align_unchecked(old_len, align);
alloc::realloc(old_ptr, layout, new_len)
};
if ptr.is_null() {
// Print a nice message in debug mode, but in release mode don't
// pull in so many dependencies related to printing so just emit an
// `unreachable` instruction.
if cfg!(debug_assertions) {
alloc::handle_alloc_error(layout);
} else {
#[cfg(target_arch = "wasm32")]
core::arch::wasm32::unreachable();
#[cfg(not(target_arch = "wasm32"))]
unreachable!();
}
}
return ptr;
}
80 changes: 3 additions & 77 deletions crates/guest-rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,94 +845,20 @@ pub use wit_bindgen_rust_macro::generate;
#[doc(hidden)]
pub use bitflags;

/// For more information about this see `./ci/rebuild-libcabi-realloc.sh`.
#[cfg(feature = "realloc")]
mod cabi_realloc;

mod pre_wit_bindgen_0_20_0;

#[cfg(docsrs)]
pub mod examples;

#[doc(hidden)]
pub mod rt {
/// This function is called from generated bindings and will be deleted by
/// the linker. The purpose of this function is to force a reference to the
/// symbol `cabi_realloc` to make its way through to the final linker
/// command line. That way `wasm-ld` will pick it up, see it needs to be
/// exported, and then export it.
///
/// For more information about this see `./ci/rebuild-libcabi-realloc.sh`.
pub fn maybe_link_cabi_realloc() {
#[cfg(target_family = "wasm")]
{
#[cfg(feature = "realloc")]
extern "C" {
fn cabi_realloc(
old_ptr: *mut u8,
old_len: usize,
align: usize,
new_len: usize,
) -> *mut u8;
}
// Force the `cabi_realloc` symbol to be referenced from here. This
// is done with a `#[used]` Rust `static` to ensure that this
// reference makes it all the way to the linker before it's
// considered for garbage collection. When the linker sees it it'll
// remove this `static` here (due to it not actually being needed)
// but the linker will have at that point seen the `cabi_realloc`
// symbol and it should get exported.
#[cfg(feature = "realloc")]
#[used]
static _NAME_DOES_NOT_MATTER: unsafe extern "C" fn(
*mut u8,
usize,
usize,
usize,
) -> *mut u8 = cabi_realloc;
}
#[cfg(feature = "realloc")]
wit_bindgen_rt::maybe_link_cabi_realloc();
}

/// NB: this function is called by a generated function in the
/// `cabi_realloc` module above. It's otherwise never explicitly called.
///
/// For more information about this see `./ci/rebuild-libcabi-realloc.sh`.
#[cfg(feature = "realloc")]
pub unsafe fn cabi_realloc(
old_ptr: *mut u8,
old_len: usize,
align: usize,
new_len: usize,
) -> *mut u8 {
use alloc::Layout;

let layout;
let ptr = if old_len == 0 {
if new_len == 0 {
return align as *mut u8;
}
layout = Layout::from_size_align_unchecked(new_len, align);
alloc::alloc(layout)
} else {
debug_assert_ne!(new_len, 0, "non-zero old_len requires non-zero new_len!");
layout = Layout::from_size_align_unchecked(old_len, align);
alloc::realloc(old_ptr, layout, new_len)
};
if ptr.is_null() {
// Print a nice message in debug mode, but in release mode don't
// pull in so many dependencies related to printing so just emit an
// `unreachable` instruction.
if cfg!(debug_assertions) {
alloc::handle_alloc_error(layout);
} else {
#[cfg(target_arch = "wasm32")]
core::arch::wasm32::unreachable();
#[cfg(not(target_arch = "wasm32"))]
unreachable!();
}
}
return ptr;
}
pub use wit_bindgen_rt::cabi_realloc;

pub use crate::pre_wit_bindgen_0_20_0::*;
}

0 comments on commit 4c7f1cf

Please sign in to comment.