Stream: general

Topic: Tarnik - a Rust macro for generating WASM GC code


view this post on Zulip Piotr Sarnacki (Nov 25 2024 at 23:29):

I couldn't find any good and ergonomic way to generate WASM GC code, and writing it by hand is kinda tedious, so I created a project to help with that: Tarnik. It's an early stage, but I like getting feedback early, so I decided to open source it already. The primary aim is to use it in jawsm and I think I will be able to do it soon. There is an example in the README and a few more in the tests. I plan to add more stuff in the next few weeks as I would really like to start using it in jawsm soon.

Let me know what you think!

Generate WASM GC code using a Rust macro. Contribute to drogus/tarnik development by creating an account on GitHub.
JavaScript to WASM compiler. Contribute to drogus/jawsm development by creating an account on GitHub.
Generate WASM GC code using a Rust macro. Contribute to drogus/tarnik development by creating an account on GitHub.

view this post on Zulip Piotr Sarnacki (Dec 02 2024 at 09:25):

I figured out I might use this thread as a way to write about updates to the tool. It's too early to create any official releases I think, but recently I've added a few more things:

So this compiles successfully now:

let module = tarnik::wasm! {
  #[export("memory")]
  memory!("memory", 1);

  type String = [mut i8];

  #[export("_start")]
  fn run() {
    let foo: String = "Hello world";
    foo[1] = 'a';

    let sum: i32 = 0;
    for byte in foo {
      sum += byte;
    }
  }
};

println!("{module}");

Next thing to implement is memory access, which shouldn't be too hard, and then ref.cast + ref.test, which should be enough for me to actually start using it in Jawsm :fingers_crossed:

view this post on Zulip Piotr Sarnacki (Dec 04 2024 at 11:01):

Another small update. I implemented casting (like: i as i64), memory store/load support and imports, so now you can write fully functioning WASI program (using p1 for simplicity):

tarnik::wasm! {
    #[export("memory")]
    memory!("memory", 1);

    #[import("wasi_snapshot_preview1", "fd_write")]
    fn write(a1: i32, a2: i32, a3: i32, a4: i32) -> i32;

    type ImmutableString = [i8];

    #[export("_start")]
    fn run() {
        let str: ImmutableString = "Hello world!";
        let i: i32 = 100;
        for c in str {
            memory[i] = c;
            i += 1;
        }
        // store io vectors
        memory[0] = 100;
        memory[4] = i;

        // `let: foo`` is small hack, if a function returns a value it needs to be somehow consumed
        let foo: i32 = write(
            1, // stdout
            0, // io vectors start
            1, // number of io vectors
            50, // where to write the result
        );
    }
};

view this post on Zulip Victor Adossi (Dec 04 2024 at 15:36):

Just chiming in to say this is pretty awesome, enjoying reading along :)

view this post on Zulip Piotr Sarnacki (Dec 08 2024 at 19:21):

Thanks @Victor Adossi!

In the recent few days I've added quite a few things:

  1. try/catch/catch_all support, along with passing argument to an exception example
  2. ref.test with ref_test! macro example
  3. len!() macro for getting length of an array
  4. Inserting data strings with data!() macro, for example data!["foo"] will insert a data entry with the string "foo" and it will return an offset example (I still need to implement getting data entry length)
Generate WASM GC code using a Rust macro. Contribute to drogus/tarnik development by creating an account on GitHub.
Generate WASM GC code using a Rust macro. Contribute to drogus/tarnik development by creating an account on GitHub.
Generate WASM GC code using a Rust macro. Contribute to drogus/tarnik development by creating an account on GitHub.

view this post on Zulip Piotr Sarnacki (Dec 11 2024 at 21:28):

Another update, and this one is exciting (at least for me). Till now I've been working on Tarnik without any real world usage, but the plan was always to use it in my other project: Jawsm compiler. I just finished rewriting about 3k lines of WAT code into about 1.5k of Rust-like code PR. I think this is a good stress test, that also uncovered a few issues, like for example problems when using expressions with casting (like -1 as i32 as i31ref) and a few other edge cases. I restructured the code to fix some of them, but I also fixed other issues so the code I already had just worked as it should. The list of latest changes:

For now I will probably slow down development of new features as I will shift my focus a bit towards Jawsm, but I'll try to improve the crate whenever I have time.

JavaScript to WASM compiler. Contribute to drogus/jawsm development by creating an account on GitHub.

Last updated: Dec 23 2024 at 13:07 UTC