diff options
| author | Rett Berg <rett@google.com> | 2019-11-16 12:38:14 -0700 | 
|---|---|---|
| committer | Rett Berg <rett@google.com> | 2019-11-16 12:38:14 -0700 | 
| commit | b27d3a088db2fac2324df2a05330801afee2e92b (patch) | |
| tree | a87dabb5e25dfc68d338d75873445bb321b15878 | |
| parent | bdcd2b8146fed98b4d56dbeff1ce71303c10cd34 (diff) | |
add example of how stack might be managed
| -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))  )  ``` | 
