summaryrefslogtreecommitdiffhomepage
path: root/wasm.html.markdown
diff options
context:
space:
mode:
authorRett Berg <rett@google.com>2019-11-16 12:38:14 -0700
committerRett Berg <rett@google.com>2019-11-16 12:38:14 -0700
commitb27d3a088db2fac2324df2a05330801afee2e92b (patch)
treea87dabb5e25dfc68d338d75873445bb321b15878 /wasm.html.markdown
parentbdcd2b8146fed98b4d56dbeff1ce71303c10cd34 (diff)
add example of how stack might be managed
Diffstat (limited to 'wasm.html.markdown')
-rw-r--r--wasm.html.markdown86
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))
)
```