| 
 | 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