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

WASM function imports #33

Open
lqd opened this issue Jul 27, 2016 · 7 comments
Open

WASM function imports #33

lqd opened this issue Jul 27, 2016 · 7 comments

Comments

@lqd
Copy link
Collaborator

lqd commented Jul 27, 2016

Related to #29 is the issue of importing wasm functions from other wasm modules (or the environment, say, a JS function). What form should it take in our rust code ?

Some more info https://github.com/WebAssembly/design/blob/master/Modules.md#imports
Example https://github.com/WebAssembly/testsuite/blob/master/imports.wast#L2

Making it work similarly to the current FFI machinery would make sense, and this would look good I think:

#[link(name="spectest")]
extern {
    fn print(i: i32);
}

However, and this might be special treatment for the spectest module (probably @kripken can shed some light on this topic), it seems in this case — as seen in the linked example — the print function is overloaded. This might be a special case because exports are apparently required to have a unique name, IIUC meaning one might not be able to produce the same exports as the spectest module provides.

If this is to be supported — which is itself an interesting question, especially since printing is right now our "only" way to test — we might need to roll our own custom attribute à la:

extern {
    #[wasm_import(module="specttest", name="print")]
    fn print_i32(i: i32);

    #[wasm_import(module="specttest", name="print")]
    fn print_i64(i: i64);
}

There may be other attributes or language features more closely matching the semantics/requirements ? Maybe #[link_args] could be of use, etc.

@brson and @eholk what do you think ?

@lqd lqd mentioned this issue Jul 27, 2016
@eddyb
Copy link

eddyb commented Jul 27, 2016

@lqd #[link_name = "print"] is probably what you want.

@brson
Copy link
Owner

brson commented Jul 27, 2016

@eddyb's syntax looks right to me. It ultimately must work exactly like any other FFI import so that 'normal' Rust code can be compiled to wasm.

@lqd
Copy link
Collaborator Author

lqd commented Jul 27, 2016

@eddyb @brson wasm has a two-level namespace, from the spec link: "All imports include two opaque names: a module name and an export name" — so we need to say which module to import, and then which function.

@eddyb
Copy link

eddyb commented Jul 27, 2016

@lqd But you already provided the solution for that:

#[link(name="spectest")]
extern {
    #[link_name = "print"]
    fn print_i32(i: i32);

    #[link_name = "print"]
    fn print_i64(i: i64);
}

@lqd
Copy link
Collaborator Author

lqd commented Jul 27, 2016

@eddyb oh ok, so yes link + link_name is exactly what we need 😄

@kripken
Copy link
Collaborator

kripken commented Jul 28, 2016

About overloading: yes, it's possible. The core issue is that when wasm imports a method, then on the web that is from JavaScript, which is not statically typed. So the function being called doesn't have types for params, etc. But wasm is typed, so (1) you must define those types for the imported function. And (2) you can import something multiple times (each to a different internal name), just because it seems arbitrary to limit that. As a result of (1)+(2) you can bind the same imported method to different internal import names that have different types, as in the examples here.

But this is indeed kind of a corner case. In practice, I'd expect to not need to care about stuff like this. spectest could have been written without it, it just happens to. On the web, it's also trivial to set up the imports on the JS side to avoid it. Bottom line, if this is annoying in any way for rust, I would just ignore it.

@lqd
Copy link
Collaborator Author

lqd commented Jul 28, 2016

@kripken super clear, thank you.
By just making the #[link_name] optional, we get good ergonomics on the simple case of a single import, while also being able to support the more complex case of multiple imports of an untyped varargs extern (and spectest at the same time).

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

No branches or pull requests

4 participants