Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add wasm32 implementation for libc #51

Merged
merged 3 commits into from
Nov 30, 2021
Merged

Conversation

nmattia
Copy link
Contributor

@nmattia nmattia commented Nov 12, 2021

Fixes #43 .

This adds a wasm32 implementation for free, malloc and realloc.
Originally written by @rodrigorc in
rust-lang/libc#1092 and adapted.

Disclaimer: I don't know rust, and I haven't really looked at the implementation; I blindly copy-pasted. This should probably be reviewed before it goes in.

@kornelski
Copy link
Owner

Thanks for the pr.

I'm a little surprised that this is needed. It sounds like a common problem for wasm. Shouldn't these be provided by emscripten or some other crate?

I'm worried that if I add these symbols, but someone links a "real" libc separately, they will conflict.

@nmattia
Copy link
Contributor Author

nmattia commented Nov 15, 2021

The target here really is wasm32-unknown-unknown, which doesn't rely on emscripten. The rust team have said they wouldn't want to support wasm in the libc crate so I reckon that shouldn't be an issue, but I'm not very experienced with rust.

There may be another crate that provides some libc functions, though I couldn't find it!

@rodrigorc
Copy link

Hi! I'm the creator of the original (rejectec) pull-request for rust-libc.

The weird thing with this situation is that Wasm has no libc at all, instead it has its own memory allocator, and rust-wasm rightfully uses this as the global allocator.

So there are no malloc/free functions anywhere. Not a big deal, because in Rust nobody uses these functions directly. Or do they? As it happens, some libraries that interact directly with native modules need to use malloc/free to pass around dynamic memory. But in Wasm there is no such modules! So what is happening?

Well, what happens is that there was some crates out there that can be used both with C native libraries or with pure Rust reimplementations of the same APIs. And some of those APIs used to pass memory blocks allocated with malloc, even though there was Rust on both sides.

This project, lodepng-rust, IIUIC, is 100% Rust, so there is little need to use malloc in the first place. I think you should replace every call to malloc/free with native Rust equivalents.

For example:

fn vec_into_raw(v: Vec<u8>) -> Result<(*mut u8, usize), crate::Error> {
    unsafe {
        let len = v.len();
        let data = lodepng_malloc(len) as *mut u8;
        if data.is_null() {
            Err(crate::Error::new(83))
        } else {
            slice::from_raw_parts_mut(data, len).clone_from_slice(&v);
            Ok((data, len))
        }
    }
}

could be reimplemented without copying as:

fn vec_into_raw(v: Vec<u8>) -> (*mut u8, usize) {
    let ptr = v.as_ptr();
    let len = v.len();
    std::mem::forget(v);
    (data, len)
}

@kornelski
Copy link
Owner

lodepng has this quirk of using raw malloc, because it exposes a C API, and callers are expected to be able to free data allocated by lodepng.

Copy link
Owner

@kornelski kornelski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change it to only use wasm32-unknown-unknown? So that -emscripten target uses real malloc?

@nmattia
Copy link
Contributor Author

nmattia commented Nov 16, 2021

@kornelski thanks for the feedback and @rodrigorc thanks for the detailed explanation!

I'll change the PR for this file only to be used in wasm32-unknown-unknown. But first I need to debug a downstream issue to make sure this isn't caused by this change.

@nmattia
Copy link
Contributor Author

nmattia commented Nov 23, 2021

Done! Here's the updated commit message for reference:

Add wasm32 implementation for libc

This adds a wasm32 implementation for free, malloc and realloc.
Originally written by @rodrigorc in
rust-lang/libc#1092 and adapted.

NOTE: This is only enabled for wasm32-unknown-unknown (target_arch = "wasm32", target_os = "unknown"), because other wasm targets (like wasm32-unknown-emscripten) may provide a libc implementation.

src/ffi.rs Outdated
mod libc;

#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
use std::path::{PathBuf};
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect this to break compilation on Windows, since the paths are later used with a different cfg. Also {Path} is a redundant syntax.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the {...}. Can you clarify the issue with Windows? I'm not very experienced with Rust, let alone conditional compilation, thanks for your patience 😅

@kornelski
Copy link
Owner

kornelski commented Nov 25, 2021

The cfg still breaks compilation on Windows. These conditions should not be for wasm. The paths are used by code later with cfg(unix). If you don't follow that code, just undo the whole change.

This adds a wasm32 implementation for `free`, `malloc` and `realloc`.
Originally written by @rodrigorc in
rust-lang/libc#1092 and adapted.

NOTE: This is only enabled for `wasm32-unknown-unknown` ([`target_arch =
"wasm32"`](https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch), [`target_os =
"unknown"`](https://doc.rust-lang.org/reference/conditional-compilation.html#target_os)), because other wasm targets (like `wasm32-unknown-emscripten`) may provide a `libc` implementation.
@nmattia
Copy link
Contributor Author

nmattia commented Nov 29, 2021

@kornelski change undone!

@kornelski kornelski merged commit 6be2aea into kornelski:main Nov 30, 2021
@kornelski
Copy link
Owner

Thank you

kornelski added a commit that referenced this pull request Nov 30, 2021
@nmattia nmattia deleted the nm-wasm32 branch November 30, 2021 08:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unable to build on wasm32-unknown-unknown due to libc malloc
3 participants