|
| 1 | +//! This module contains a canonical definition of the `cabi_realloc` function |
| 2 | +//! for the component model. |
| 3 | +//! |
| 4 | +//! The component model's canonical ABI for representing datatypes in memory |
| 5 | +//! makes use of this function when transferring lists and strings, for example. |
| 6 | +//! This function behaves like C's `realloc` but also takes alignment into |
| 7 | +//! account. |
| 8 | +//! |
| 9 | +//! Components are notably not required to export this function, but nearly |
| 10 | +//! all components end up doing so currently. This definition in the standard |
| 11 | +//! library removes the need for all compilations to define this themselves. |
| 12 | +//! |
| 13 | +//! More information about the canonical ABI can be found at |
| 14 | +//! <https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md> |
| 15 | +//! |
| 16 | +//! Note that the name of this function is not standardized in the canonical ABI |
| 17 | +//! at this time. Instead it's a convention of the "componentization process" |
| 18 | +//! where a core wasm module is converted to a component to use this name. |
| 19 | +//! Additionally this is not the only possible definition of this function, so |
| 20 | +//! this is defined as a "weak" symbol. This means that other definitions are |
| 21 | +//! allowed to overwrite it if they are present in a compilation. |
| 22 | +
|
| 23 | +use crate::alloc::{self, Layout}; |
| 24 | +use crate::ptr; |
| 25 | + |
| 26 | +#[used] |
| 27 | +static FORCE_CODEGEN_OF_CABI_REALLOC: unsafe extern "C" fn( |
| 28 | + *mut u8, |
| 29 | + usize, |
| 30 | + usize, |
| 31 | + usize, |
| 32 | +) -> *mut u8 = cabi_realloc; |
| 33 | + |
| 34 | +#[linkage = "weak"] |
| 35 | +#[no_mangle] |
| 36 | +pub unsafe extern "C" fn cabi_realloc( |
| 37 | + old_ptr: *mut u8, |
| 38 | + old_len: usize, |
| 39 | + align: usize, |
| 40 | + new_len: usize, |
| 41 | +) -> *mut u8 { |
| 42 | + let layout; |
| 43 | + let ptr = if old_len == 0 { |
| 44 | + if new_len == 0 { |
| 45 | + return ptr::without_provenance_mut(align); |
| 46 | + } |
| 47 | + layout = Layout::from_size_align_unchecked(new_len, align); |
| 48 | + alloc::alloc(layout) |
| 49 | + } else { |
| 50 | + debug_assert_ne!(new_len, 0, "non-zero old_len requires non-zero new_len!"); |
| 51 | + layout = Layout::from_size_align_unchecked(old_len, align); |
| 52 | + alloc::realloc(old_ptr, layout, new_len) |
| 53 | + }; |
| 54 | + if ptr.is_null() { |
| 55 | + // Print a nice message in debug mode, but in release mode don't |
| 56 | + // pull in so many dependencies related to printing so just emit an |
| 57 | + // `unreachable` instruction. |
| 58 | + if cfg!(debug_assertions) { |
| 59 | + alloc::handle_alloc_error(layout); |
| 60 | + } else { |
| 61 | + super::abort_internal(); |
| 62 | + } |
| 63 | + } |
| 64 | + return ptr; |
| 65 | +} |
0 commit comments