diff options
-rw-r--r-- | wasm.html.markdown | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/wasm.html.markdown b/wasm.html.markdown index 98bfc000..92831e69 100644 --- a/wasm.html.markdown +++ b/wasm.html.markdown @@ -222,6 +222,92 @@ contributors: ) ) (export "apply_cos64" (func $apply_cos64)) + + ;; Demonstration of how this C code might be written by hand + ;; + ;; typedef struct { + ;; int a; + ;; int b; + ;; } sum_struct_t; + ;; + ;; sum_struct_t sum_struct_create(int a, int b) { + ;; return (sum_struct_t){a, b}; + ;; } + ;; + ;; int sum_local() { + ;; sum_struct_t s = sum_struct_create(40, 2); + ;; return s.a + s.b; + ;; } + ;; + ;; Wasm is a stack-based language, but for returning values more complicated + ;; than an int/float, a memory stack has to be manually managed. One ;; + ;; approach is to use a mutable global to store the stack_ptr. We give + ;; ourselves 1MiB of mem-stack and grow it downwards. + ;; + ;; Note: we are differentiating from the memstack (stack stored in memory) + ;; and the "stack", which wasm implicitly uses to to pass and return values. + (global $memstack_ptr (mut i32) (i32.const 65536)) + + ;; structs can only be returned by reference + (func $sum_struct_create + (param $sum_struct_ptr i32) + (param $var$a i32) + (param $var$b i32) + ;; c// sum_struct_ptr->a = a; + (i32.store + (get_local $sum_struct_ptr) + (get_local $var$a) + ) + + ;; c// sum_struct_ptr->b = b; + (i32.store offset=4 + (get_local $sum_struct_ptr) + (get_local $var$b) + ) + ) + + (func $sum_local (result i32) + (local $var$sum_struct$a i32) + (local $var$sum_struct$b i32) + (local $local_memstack_ptr i32) + + ;; reserve stack space + (i32.sub + (get_global $memstack_ptr) + (i32.const 8) + ) + tee_local $local_memstack_ptr ;; tee both stores and returns given value + set_global $memstack_ptr + + ;; call the function, storing the result in the stack + (call $sum_struct_create + ((;$sum_struct_ptr=;) get_local $local_memstack_ptr) + ((;$var$a=;) i32.const 40) + ((;$var$b=;) i32.const 2) + ) + + ;; retrieve values from struct + (set_local $var$sum_struct$a + (i32.load offset=0 (get_local $local_memstack_ptr)) + ) + (set_local $var$sum_struct$b + (i32.load offset=4 (get_local $local_memstack_ptr)) + ) + + ;; unreserve stack space + (set_global $memstack_ptr + (i32.add + (get_local $local_memstack_ptr) + (i32.const 8) + ) + ) + + (i32.add + (get_local $var$sum_struct$a) + (get_local $var$sum_struct$b) + ) + ) + (export "sum_local" (func $sum_local)) ) ``` |