rustwasm / walrus

Walrus is a WebAssembly transformation library šŸŒŠšŸ˜
https://docs.rs/walrus
Apache License 2.0
385 stars 62 forks source link

Ergonomics for codegen #169

Open icefoxen opened 4 years ago

icefoxen commented 4 years ago

Motivation

Hi again, I'm continuing my use-walrus-as-a-compiler-backend adventure, and there's a couple things that have caused me some grief. After thinking about it more it feels like this is because walrus is currently mostly designed to take some existing wasm module as input and do stuff to it, and less to generate these modules from whole cloth. However, it's currently still the best crate available for generating wasm, as unlike most it a) is actually up to date and feels like the developers actually use it, and to a lesser extent b) is really nice because it does a lot of the accounting of identifiers and stuff for you.

However, this accounting has also caused me grief a few times. Most notably:

Proposed Solution

I'd happily try to make a PR for a TableBuilder and MemoryBuilder type, if you wanted. Seems easy enough, even if I have no idea what ElementKind actually is -- can't find any references to that in the wasm spec, so I assume it's newer stuff that hasn't been finalized yet. My existing code is halfway there already.

As for the function stuff, I'm not sure what the best course of action is. One could make a function to reserve a FunctionId and then use it later to actually build the function. You could make it possible to kindasorta "disconnect" a FunctionBuilder from a particular Function, changing the reference into an Rc or something, or perhaps more simply just make it possible to create a Function, then later replace its body with a new, fresh FunctionBuilder you've created. Actually this might be possible with InstrSeq, but I don't quite understand how that portion of walrus works yet.

Alternatives

Don't do this, I guess? This is work I need to do anyway, so I might as well design it to be upstreamed if you guys want it. I could contribute some extra docs or examples if you prefer, since the existing ones are a little minimal.

alexcrichton commented 4 years ago

Sorry for the delay, but PRs for these would definitely be welcome!

FWIW ElementKind mostly has to do with the reference types and bulk memory proposal, but you can largely ignore it most likel. Otherwise I think whatever APIs make sense here should be good to add!

NicholasLYang commented 3 years ago

Happy to work on this (exploring using walrus as a compiler backend as well). There's already a FunctionKind::Uninitialized, so we can use that. It could be as simple as adding a ModuleFunctions::add_uninitialized that takes in a type id and adds an uninitialized function to the arena. Then ModuleFunctions::get_mut should handle the swapping.

We will have to emit a proper error on trying to emit an uninitialized function instead of panicking, as it's now a valid error.

If that sounds good, I'll start a PR

NicholasLYang commented 3 years ago

After looking at the code some more, the error handling is actually the tricky bit. Right now fn emit doesn't return a Result, so we can't error cleanly on trying to emit an uninitialized function. We could change that, but it'd be a somewhat larger change.

NicholasLYang commented 3 years ago

Bump @alexcrichton