# In-Class Exercise 11: WebAssembly

In this exercise, we will look at WebAssembly for execution on an operating system (i.e., without browser).

1. Download the WASI SDK. This contains clang and a libc compiled for the WASI interface to operating systems.
  - https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-17

2. Compile a first, simple function to WebAssembly and print the textual assembly. Try to follow the layout of the stack inside the function.

    echo "int increment(int x) { return x + 1; }" > test.c
    /path/to/wasi-sdk-17.0/bin/clang -O1 -S -o test.s test.c

3. Compile the following function, again with -O1, and look at the structure of the loop. Use the WASM specification or the MDN reference to find, how the loop and br instructions work.

  - https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-instr-control
  - https://developer.mozilla.org/en-US/docs/WebAssembly/Reference

    unsigned fac(unsigned x) {
      unsigned r = 1;
      while (x)
        r *= x--;
      return r;
    }

4. Change the type of `r` to `unsigned long long` and the return type. How does this impact the output and the types of the local variables?

5. Compile the following code. How are stack allocations managed?

    void ext(int*);
    void foo() { int x; ext(&x); }

6. Compile the following code, which contains an irreducible loop. How is this compiled to WebAssembly?

    void f(int);
    int g(int);
    void irred(int x) {
      if (x < 0)
        goto foo;
      while (x) {
        f(x);
      foo:
        x = g(x);
      }
    }

7. Add a main function and add, e.g., a call to `printf` and compile the code with the options `-O1 -o test.wasm test.c`. Use `llvm-objdump -d test.wasm | less` to inspect the file. (Note: if you have wabt installed, you can preferably/also use `wasm-objdump -xd test.wasm`.)


If there's time left, you can also use Wasmer for a compilation to machine code.

8. Download wasmer.

  - https://github.com/wasmerio/wasmer/releases/tag/v3.1.0

9. Run the following command and use `objdump` to inspect the machine code. Replace `--singlepass` with `--cranelift` or `--llvm` to change the compilation back-end. Also notice the differences in compilation speed.

    /path/to/wasmer-linux-amd64/bin/wasmer create-obj --singlepass -o test.o test.wasm