1;;! component_model_async = true
2;;! multi_memory = true
3;;! reference_types = true
4
5;; backpressure.inc
6(component
7  (core module $m
8    (import "" "backpressure.inc" (func $backpressure-inc))
9  )
10  (core func $backpressure-inc (canon backpressure.inc))
11  (core instance $i (instantiate $m (with "" (instance (export "backpressure.inc" (func $backpressure-inc))))))
12)
13
14;; backpressure.dec
15(component
16  (core module $m
17    (import "" "backpressure.dec" (func $backpressure-dec))
18  )
19  (core func $backpressure-dec (canon backpressure.dec))
20  (core instance $i (instantiate $m (with "" (instance (export "backpressure.dec" (func $backpressure-dec))))))
21)
22
23;; task.return
24(component
25  (core module $m
26    (import "" "task.return" (func $task-return (param i32)))
27  )
28  (core func $task-return (canon task.return (result u32)))
29  (core instance $i (instantiate $m (with "" (instance (export "task.return" (func $task-return))))))
30)
31
32;; waitable-set.wait
33(component
34  (core module $libc (memory (export "memory") 1))
35  (core instance $libc (instantiate $libc))
36  (core module $m
37    (import "" "waitable-set.wait" (func $waitable-set-wait (param i32 i32) (result i32)))
38  )
39  (core func $waitable-set-wait (canon waitable-set.wait (memory $libc "memory")))
40  (core instance $i (instantiate $m (with "" (instance (export "waitable-set.wait" (func $waitable-set-wait))))))
41)
42
43;; waitable-set.poll
44(component
45  (core module $libc (memory (export "memory") 1))
46  (core instance $libc (instantiate $libc))
47  (core module $m
48    (import "" "waitable-set.poll" (func $waitable-set-poll (param i32 i32) (result i32)))
49  )
50  (core func $waitable-set-poll (canon waitable-set.poll (memory $libc "memory")))
51  (core instance $i (instantiate $m (with "" (instance (export "waitable-set.poll" (func $waitable-set-poll))))))
52)
53
54;; thread.yield
55(component
56  (core module $m
57    (import "" "thread.yield" (func $thread-yield (result i32)))
58  )
59  (core func $thread-yield (canon thread.yield))
60  (core instance $i (instantiate $m (with "" (instance (export "thread.yield" (func $thread-yield))))))
61)
62
63;; subtask.drop
64(component
65  (core module $m
66    (import "" "subtask.drop" (func $subtask-drop (param i32)))
67  )
68  (core func $subtask-drop (canon subtask.drop))
69  (core instance $i (instantiate $m (with "" (instance (export "subtask.drop" (func $subtask-drop))))))
70)
71
72;; subtask.cancel
73(component
74  (core module $m
75    (import "" "subtask.cancel" (func $subtask-drop (param i32) (result i32)))
76  )
77  (core func $subtask-cancel (canon subtask.cancel))
78  (core instance $i (instantiate $m (with "" (instance (export "subtask.cancel" (func $subtask-cancel))))))
79)
80
81;; Test that some intrinsics are exempt from may-leave checks
82(component
83  (core func $backpressure.inc (canon backpressure.inc))
84  (core func $backpressure.dec (canon backpressure.dec))
85  (core func $context.get (canon context.get i32 0))
86  (core func $context.set (canon context.set i32 0))
87
88  (core module $DM
89    (import "" "backpressure.inc" (func $backpressure.inc))
90    (import "" "backpressure.dec" (func $backpressure.dec))
91    (import "" "context.get" (func $context.get (result i32)))
92    (import "" "context.set" (func $context.set (param i32)))
93
94    (global $g (mut i32) (i32.const 0))
95
96    (func (export "run")
97      (call $context.set (i32.const 100))
98    )
99    (func (export "post-return")
100      call $backpressure.inc
101      call $backpressure.dec
102
103      ;; context.get should be what was set in `run`
104      call $context.get
105      i32.const 100
106      i32.ne
107      if unreachable end
108
109      i32.const 32
110      call $context.set
111    )
112  )
113  (core instance $dm (instantiate $DM (with "" (instance
114    (export "backpressure.inc" (func $backpressure.inc))
115    (export "backpressure.dec" (func $backpressure.dec))
116    (export "context.get" (func $context.get))
117    (export "context.set" (func $context.set))
118  ))))
119  (func (export "run")
120    (canon lift (core func $dm "run") (post-return (func $dm "post-return"))))
121)
122
123(assert_return (invoke "run"))
124
125;; Test calling intrinsics during `realloc` and their values should be set for
126;; when main function is called
127(component
128  (core func $backpressure.inc (canon backpressure.inc))
129  (core func $backpressure.dec (canon backpressure.dec))
130  (core func $context.get (canon context.get i32 0))
131  (core func $context.set (canon context.set i32 0))
132
133  (core module $libc
134    (import "" "backpressure.inc" (func $backpressure.inc))
135    (import "" "backpressure.dec" (func $backpressure.dec))
136    (import "" "context.get" (func $context.get (result i32)))
137    (import "" "context.set" (func $context.set (param i32)))
138
139    (memory (export "memory") 1)
140    (func (export "realloc") (param i32 i32 i32 i32) (result i32)
141      (if (i32.ne (local.get 0) (i32.const 0)) (then (unreachable)))
142      (if (i32.ne (local.get 1) (i32.const 0)) (then (unreachable)))
143      (if (i32.ne (local.get 2) (i32.const 1)) (then (unreachable)))
144      (if (i32.ne (local.get 3) (i32.const 2)) (then (unreachable)))
145
146      call $context.get
147      i32.const 0
148      i32.ne
149      if unreachable end
150
151      i32.const 100
152      call $context.set
153
154      call $backpressure.inc
155      call $backpressure.dec
156
157      i32.const 200
158    )
159  )
160
161  (core instance $libc (instantiate $libc (with "" (instance
162    (export "backpressure.inc" (func $backpressure.inc))
163    (export "backpressure.dec" (func $backpressure.dec))
164    (export "context.get" (func $context.get))
165    (export "context.set" (func $context.set))
166  ))))
167
168  (core module $M
169    (import "" "backpressure.inc" (func $backpressure.inc))
170    (import "" "backpressure.dec" (func $backpressure.dec))
171    (import "" "context.get" (func $context.get (result i32)))
172    (import "" "context.set" (func $context.set (param i32)))
173
174    (func (export "run") (param i32 i32)
175      ;; ptr/len assertion
176      (if (i32.ne (local.get 0) (i32.const 200)) (then (unreachable)))
177      (if (i32.ne (local.get 1) (i32.const 2)) (then (unreachable)))
178
179      call $backpressure.inc
180      call $backpressure.dec
181
182      ;; context.get should be what was set in `realloc`
183      (if (i32.ne (call $context.get) (i32.const 100)) (then (unreachable)))
184    )
185  )
186  (core instance $m (instantiate $M (with "" (instance
187    (export "backpressure.inc" (func $backpressure.inc))
188    (export "backpressure.dec" (func $backpressure.dec))
189    (export "context.get" (func $context.get))
190    (export "context.set" (func $context.set))
191  ))))
192  (func (export "run") (param "x" string)
193    (canon lift (core func $m "run")
194      (realloc (func $libc "realloc"))
195      (memory $libc "memory")
196    )
197  )
198)
199
200(assert_return (invoke "run" (str.const "hi")))
201
202;; Test when realloc is called to communicate return values that various
203;; intrinsics work and have their expected values.
204(component
205  (component $A
206    (core module $libc (memory (export "memory") 1))
207    (core instance $libc (instantiate $libc))
208
209    (core func $task.return (canon task.return (result string) (memory $libc "memory")))
210
211    (core module $m
212      (import "" "task.return" (func $task.return (param i32 i32)))
213      (import "" "memory" (memory 1))
214      (func (export "run-sync") (result i32)
215        i32.const 40
216        i32.const 100
217        i32.store offset=0
218
219        i32.const 40
220        i32.const 2
221        i32.store offset=4
222
223        i32.const 40
224      )
225      (func (export "run-async") (result i32)
226        i32.const 100
227        i32.const 2
228        call $task.return
229        i32.const 0 ;; CALLBACK_CODE_EXIT
230      )
231
232      (func (export "run-async-cb") (param i32 i32 i32) (result i32) unreachable)
233      (data (i32.const 100) "hi")
234    )
235    (core instance $m (instantiate $m
236      (with "" (instance
237        (export "task.return" (func $task.return))
238        (export "memory" (memory $libc "memory"))
239      ))
240    ))
241    (func (export "run-sync") (result string)
242      (canon lift (core func $m "run-sync") (memory $libc "memory"))
243    )
244    (func (export "run-async") async (result string)
245      (canon lift (core func $m "run-async") (memory $libc "memory") async
246          (callback (func $m "run-async-cb")))
247    )
248  )
249
250  (component $B
251    (import "a" (instance $a
252      (export "run-sync" (func (result string)))
253      (export "run-async" (func async (result string)))
254    ))
255
256    (core func $backpressure.inc (canon backpressure.inc))
257    (core func $backpressure.dec (canon backpressure.dec))
258    (core func $context.get (canon context.get i32 0))
259    (core func $context.set (canon context.set i32 0))
260
261    (core module $libc
262      (import "" "backpressure.inc" (func $backpressure.inc))
263      (import "" "backpressure.dec" (func $backpressure.dec))
264      (import "" "context.get" (func $context.get (result i32)))
265      (import "" "context.set" (func $context.set (param i32)))
266
267      (memory (export "memory") 1)
268      (func (export "realloc") (param i32 i32 i32 i32) (result i32)
269        (if (i32.ne (local.get 0) (i32.const 0)) (then (unreachable)))
270        (if (i32.ne (local.get 1) (i32.const 0)) (then (unreachable)))
271        (if (i32.ne (local.get 2) (i32.const 1)) (then (unreachable)))
272        (if (i32.ne (local.get 3) (i32.const 2)) (then (unreachable)))
273
274        (if (i32.ne (call $context.get) (i32.const 400)) (then (unreachable)))
275        (call $context.set (i32.const 500))
276
277        call $backpressure.inc
278        call $backpressure.dec
279
280        i32.const 200
281      )
282    )
283
284    (core instance $libc (instantiate $libc (with "" (instance
285      (export "backpressure.inc" (func $backpressure.inc))
286      (export "backpressure.dec" (func $backpressure.dec))
287      (export "context.get" (func $context.get))
288      (export "context.set" (func $context.set))
289    ))))
290
291    (core func $sync-to-sync
292      (canon lower (func $a "run-sync")
293        (memory $libc "memory")
294        (realloc (func $libc "realloc"))
295      )
296    )
297    (core func $async-to-sync
298      (canon lower (func $a "run-sync")
299        async
300        (memory $libc "memory")
301        (realloc (func $libc "realloc"))
302      )
303    )
304    (core func $sync-to-async
305      (canon lower (func $a "run-async")
306        (memory $libc "memory")
307        (realloc (func $libc "realloc"))
308      )
309    )
310    (core func $async-to-async
311      (canon lower (func $a "run-async")
312        async
313        (memory $libc "memory")
314        (realloc (func $libc "realloc"))
315      )
316    )
317
318    (core module $M
319      (import "" "context.set" (func $context.set (param i32)))
320      (import "" "context.get" (func $context.get (result i32)))
321      (import "" "sync-to-sync" (func $sync-to-sync (param i32)))
322      (import "" "sync-to-async" (func $sync-to-async (param i32)))
323      (import "" "async-to-sync" (func $async-to-sync (param i32) (result i32)))
324      (import "" "async-to-async" (func $async-to-async (param i32) (result i32)))
325
326      ;; set this tasks's context before calling $run, in calling $run the
327      ;; runtime will then call `realloc` above for the string return value
328      ;; which should see our 400 value. That will then set 500 which we should
329      ;; then see after the return.
330
331      (func (export "sync-to-sync")
332        (call $context.set (i32.const 400))
333        (call $sync-to-sync (i32.const 20))
334        (if (i32.ne (call $context.get) (i32.const 500)) (then (unreachable)))
335      )
336
337      (func (export "sync-to-async")
338        (call $context.set (i32.const 400))
339        (call $sync-to-async (i32.const 20))
340        (if (i32.ne (call $context.get) (i32.const 500)) (then (unreachable)))
341      )
342
343      (func (export "async-to-sync")
344        (call $context.set (i32.const 400))
345        (if
346          (i32.ne
347            (call $async-to-sync (i32.const 20))
348            (i32.const 2) ;; RETURNED
349          )
350          (then (unreachable))
351        )
352        (if (i32.ne (call $context.get) (i32.const 500)) (then (unreachable)))
353      )
354
355      (func (export "async-to-async")
356        (call $context.set (i32.const 400))
357        (if
358          (i32.ne
359            (call $async-to-async (i32.const 20))
360            (i32.const 2) ;; RETURNED
361          )
362          (then (unreachable))
363        )
364        (if (i32.ne (call $context.get) (i32.const 500)) (then (unreachable)))
365      )
366    )
367    (core instance $m (instantiate $M (with "" (instance
368      (export "context.set" (func $context.set))
369      (export "context.get" (func $context.get))
370      (export "sync-to-sync" (func $sync-to-sync))
371      (export "sync-to-async" (func $sync-to-async))
372      (export "async-to-sync" (func $async-to-sync))
373      (export "async-to-async" (func $async-to-async))
374    ))))
375    (func (export "sync-to-sync") async (canon lift (core func $m "sync-to-sync")))
376    (func (export "sync-to-async") async (canon lift (core func $m "sync-to-async")))
377    (func (export "async-to-sync") async (canon lift (core func $m "async-to-sync")))
378    (func (export "async-to-async") async (canon lift (core func $m "async-to-async")))
379  )
380
381  (instance $a (instantiate $A))
382  (instance $b (instantiate $B (with "a" (instance $a))))
383  (export "sync-to-sync" (func $b "sync-to-sync"))
384  (export "sync-to-async" (func $b "sync-to-async"))
385  (export "async-to-sync" (func $b "async-to-sync"))
386  (export "async-to-async" (func $b "async-to-async"))
387)
388
389(assert_return (invoke "sync-to-sync"))
390(assert_return (invoke "sync-to-async"))
391(assert_return (invoke "async-to-sync"))
392(assert_return (invoke "async-to-async"))
393
394;; Same as above, but when calling the host.
395(component
396  (import "host" (instance $host
397    (export "return-hi" (func (result string)))
398  ))
399
400  (core func $backpressure.inc (canon backpressure.inc))
401  (core func $backpressure.dec (canon backpressure.dec))
402  (core func $context.get (canon context.get i32 0))
403  (core func $context.set (canon context.set i32 0))
404
405  (core module $libc
406    (import "" "backpressure.inc" (func $backpressure.inc))
407    (import "" "backpressure.dec" (func $backpressure.dec))
408    (import "" "context.get" (func $context.get (result i32)))
409    (import "" "context.set" (func $context.set (param i32)))
410
411    (memory (export "memory") 1)
412    (func (export "realloc") (param i32 i32 i32 i32) (result i32)
413      (if (i32.ne (local.get 0) (i32.const 0)) (then (unreachable)))
414      (if (i32.ne (local.get 1) (i32.const 0)) (then (unreachable)))
415      (if (i32.ne (local.get 2) (i32.const 1)) (then (unreachable)))
416      (if (i32.ne (local.get 3) (i32.const 2)) (then (unreachable)))
417
418      (if (i32.ne (call $context.get) (i32.const 400)) (then (unreachable)))
419      (call $context.set (i32.const 500))
420
421      call $backpressure.inc
422      call $backpressure.dec
423
424      i32.const 200
425    )
426  )
427
428  (core instance $libc (instantiate $libc (with "" (instance
429    (export "backpressure.inc" (func $backpressure.inc))
430    (export "backpressure.dec" (func $backpressure.dec))
431    (export "context.get" (func $context.get))
432    (export "context.set" (func $context.set))
433  ))))
434
435  (core func $run
436    (canon lower (func $host "return-hi")
437      (memory $libc "memory")
438      (realloc (func $libc "realloc"))
439    )
440  )
441
442  (core module $M
443    (import "" "context.set" (func $context.set (param i32)))
444    (import "" "context.get" (func $context.get (result i32)))
445    (import "" "run" (func $run (param i32)))
446
447    (func (export "run")
448      ;; set this tasks's context before calling $run, in calling $run the
449      ;; runtime will then call `realloc` above for the string return value
450      ;; which should see our 400 value. That will then set 500 which we
451      ;; should then see after the return.
452      (call $context.set (i32.const 400))
453      (call $run (i32.const 20))
454      (if (i32.ne (call $context.get) (i32.const 500)) (then (unreachable)))
455    )
456  )
457  (core instance $m (instantiate $M (with "" (instance
458    (export "context.set" (func $context.set))
459    (export "context.get" (func $context.get))
460    (export "run" (func $run))
461  ))))
462  (func (export "run") (canon lift (core func $m "run")))
463)
464
465(assert_return (invoke "run"))
466
467;; Test when realloc is called to communicate stream/future values that various
468;; intrinsics work and have their expected values.
469(component
470  ;; Component that will drive the reader forward and write to the future/stream
471  (component $writer
472    (type $FT (future string))
473    (type $ST (stream string))
474    ;; The reader will provide runner functions for futures and streams separately
475    (import "reader" (instance $reader
476      (export "run-future" (func async (param "future" $FT) (result u32)))
477      (export "run-stream" (func async (param "stream" $ST) (result u32)))
478    ))
479    (core module $libc
480      (memory (export "memory") 1))
481    (core instance $libc (instantiate $libc))
482    (core func $run-reader-future (canon lower (func $reader "run-future") (memory $libc "memory") async))
483    (core func $run-reader-stream (canon lower (func $reader "run-stream") (memory $libc "memory") async))
484    (core module $m
485      (import "" "future.write" (func $future.write (param i32 i32) (result i32)))
486      (import "" "stream.write" (func $stream.write (param i32 i32 i32) (result i32)))
487      (import "" "waitable.join" (func $waitable.join (param i32 i32)))
488      (import "" "waitable-set.new" (func $waitable-set.new (result i32)))
489      (import "" "stream.new" (func $stream.new (result i64)))
490      (import "" "future.new" (func $future.new (result i64)))
491      (import "" "task.return" (func $task.return (param i32)))
492      (import "" "run-reader-future" (func $run-reader-future (param i32 i32) (result i32)))
493      (import "" "run-reader-stream" (func $run-reader-stream (param i32 i32) (result i32)))
494      (import "" "memory" (memory 1))
495
496      (global $ws (mut i32) (i32.const 0))
497      (global $fw (mut i32) (i32.const 0))
498      (global $sw (mut i32) (i32.const 0))
499      (global $state (mut i32) (i32.const 0))
500      (global $future-subtask (mut i32) (i32.const 0))
501      (global $stream-subtask (mut i32) (i32.const 0))
502      (global $future-retp i32 (i32.const 0x60))
503      (global $stream-retp i32 (i32.const 0x70))
504
505      (func (export "run") (result i32)
506        (local $ret i32) (local $ret64 i64)
507        (local $fr i32) (local $sr i32)
508
509        ;; store address and length of string
510        (i32.store offset=0 (i32.const 40) (i32.const 0x100))
511        (i32.store offset=4 (i32.const 40) (i32.const 2))
512
513        (local.set $ret64 (call $future.new))
514        (local.set $fr (i32.wrap_i64 (local.get $ret64)))
515        (global.set $fw (i32.wrap_i64 (i64.shr_u (local.get $ret64) (i64.const 32))))
516        (local.set $ret64 (call $stream.new))
517        (local.set $sr (i32.wrap_i64 (local.get $ret64)))
518        (global.set $sw (i32.wrap_i64 (i64.shr_u (local.get $ret64) (i64.const 32))))
519
520        (local.set $ret (call $run-reader-future (local.get $fr) (global.get $future-retp)))
521        (global.set $future-subtask (i32.shr_u (local.get $ret) (i32.const 4)))
522        (local.set $ret (call $future.write (global.get $fw) (i32.const 40)))
523        (if (i32.ne (i32.const 0 (; COMPLETED ;)) (local.get $ret))
524          (then unreachable))
525
526        (local.set $ret (call $run-reader-stream (local.get $sr) (global.get $stream-retp)))
527        (global.set $stream-subtask (i32.shr_u (local.get $ret) (i32.const 4)))
528        (local.set $ret (call $stream.write (global.get $sw) (i32.const 40) (i32.const 1)))
529        (if (i32.ne (i32.const 0x10 (; COMPLETED | 1<<4 ;)) (local.get $ret)) (then (unreachable)))
530
531        ;; Create a waitable set and join both subtasks to wait for both to complete
532        (global.set $ws (call $waitable-set.new))
533        (call $waitable.join (global.get $stream-subtask) (global.get $ws))
534        (call $waitable.join (global.get $future-subtask) (global.get $ws))
535        (i32.or (i32.const 2 (; WAIT ;)) (i32.shl (global.get $ws) (i32.const 4)))
536      )
537
538      (global $future-completed (mut i32) (i32.const 0))
539      (global $stream-completed (mut i32) (i32.const 0))
540
541      ;; Callback invoked when a subtask completes. Since we joined both subtasks to the
542      ;; same waitable set, this will be called once for each completion. We track which
543      ;; subtasks have completed and only return when both are done.
544      (func (export "run-cb") (param $event_code i32) (param $index i32) (param $payload i32) (result i32)
545        (if (i32.ne (local.get $event_code) (i32.const 1 (; SUBTASK ;))) (then (unreachable)))
546        (if (i32.ne (local.get $payload) (i32.const 2 (; RETURNED ;))) (then (unreachable)))
547
548        ;; Track which subtask completed
549        (if (i32.eq (local.get $index) (global.get $future-subtask))
550          (then
551            (if (i32.ne (i32.load (global.get $future-retp)) (i32.const 42)) (then (unreachable)))
552            (global.set $future-completed (i32.const 1)))
553          (else
554            (if (i32.eq (local.get $index) (global.get $stream-subtask))
555              (then
556              (if (i32.ne (i32.load (global.get $stream-retp)) (i32.const 42)) (then (unreachable)))
557                (global.set $stream-completed (i32.const 1)))
558              (else unreachable))))
559
560        ;; If both completed, exit; otherwise keep waiting
561        (if (result i32)
562          (i32.and (i32.eq (global.get $future-completed) (i32.const 1))
563                   (i32.eq (global.get $stream-completed) (i32.const 1)))
564            (then
565              (call $task.return (i32.const 42))
566              (i32.const 0 (; EXIT ;)))
567            (else
568              (i32.or (i32.const 2 (; WAIT ;)) (i32.shl (global.get $ws) (i32.const 4)))))
569      )
570
571      (data (i32.const 0x100) "hi")
572    )
573    (canon future.new $FT (core func $future.new))
574    (canon future.write $FT async
575      (memory $libc "memory") (core func $future.write))
576    (canon stream.new $ST (core func $stream.new))
577    (canon stream.write $ST async
578      (memory $libc "memory") (core func $stream.write))
579    (canon waitable.join (core func $waitable.join))
580    (canon waitable-set.new (core func $waitable-set.new))
581    (canon task.return (result u32) (memory $libc "memory") (core func $task.return))
582    (canon context.set i32 0 (core func $context.set))
583
584    (core instance $M (instantiate $m (with "" (instance
585      (export "memory" (memory $libc "memory"))
586      (export "future.new" (func $future.new))
587      (export "future.write" (func $future.write))
588      (export "stream.new" (func $stream.new))
589      (export "stream.write" (func $stream.write))
590      (export "waitable.join" (func $waitable.join))
591      (export "waitable-set.new" (func $waitable-set.new))
592      (export "task.return" (func $task.return))
593      (export "run-reader-future" (func $run-reader-future))
594      (export "run-reader-stream" (func $run-reader-stream))
595    ))))
596
597    (func (export "run") async (result u32)
598      (canon lift (core func $M "run") (memory $libc "memory")
599        async (callback (func $M "run-cb")))
600    )
601  )
602
603  (component $reader
604    (core module $libc
605      (import "" "backpressure.inc" (func $backpressure.inc))
606      (import "" "backpressure.dec" (func $backpressure.dec))
607      (import "" "context.get" (func $context.get (result i32)))
608      (import "" "context.set" (func $context.set (param i32)))
609
610      (memory (export "memory") 1)
611      (func (export "realloc") (param i32 i32 i32 i32) (result i32)
612        (if (i32.ne (local.get 0) (i32.const 0)) (then (unreachable)))
613        (if (i32.ne (local.get 1) (i32.const 0)) (then (unreachable)))
614        (if (i32.ne (local.get 2) (i32.const 1)) (then (unreachable)))
615        (if (i32.ne (local.get 3) (i32.const 2)) (then (unreachable)))
616
617        call $context.get
618        i32.const 400
619        i32.ne
620        if unreachable end
621
622        i32.const 500
623        call $context.set
624
625        call $backpressure.inc
626        call $backpressure.dec
627
628        i32.const 200
629      )
630    )
631
632    (core func $backpressure.inc (canon backpressure.inc))
633    (core func $backpressure.dec (canon backpressure.dec))
634    (core func $context.get (canon context.get i32 0))
635    (core func $context.set (canon context.set i32 0))
636
637    (core instance $libc (instantiate $libc (with "" (instance
638      (export "backpressure.inc" (func $backpressure.inc))
639      (export "backpressure.dec" (func $backpressure.dec))
640      (export "context.get" (func $context.get))
641      (export "context.set" (func $context.set))
642    ))))
643
644    (type $FT (future string))
645    (type $ST (stream string))
646    (canon future.new $FT (core func $future.new))
647    (canon future.read $FT
648      (memory $libc "memory") (realloc (func $libc "realloc")) (core func $future.read))
649    (canon stream.new $ST (core func $stream.new))
650    (canon stream.read $ST
651      (memory $libc "memory") (realloc (func $libc "realloc")) (core func $stream.read))
652    (canon waitable.join (core func $waitable.join))
653    (canon waitable-set.new (core func $waitable-set.new))
654    (canon waitable-set.wait (memory $libc "memory") (core func $waitable-set.wait))
655    (canon task.return (result u32) (memory $libc "memory") (core func $task.return))
656
657    (core module $m
658      (import "" "future.read" (func $future.read (param i32 i32) (result i32)))
659      (import "" "stream.read" (func $stream.read (param i32 i32 i32) (result i32)))
660      (import "" "context.set" (func $context.set (param i32)))
661      (import "" "context.get" (func $context.get (result i32)))
662      (import "" "task.return" (func $task.return (param i32)))
663      (import "" "memory" (memory 1))
664
665      ;; Set context[0] to 400, then read the future, which should call realloc and set
666      ;; context[0] to 500, then check that we see that value.
667      (func (export "run-future") (param $fr i32) (result i32)
668        (local $ret i32)
669
670        (call $context.set (i32.const 400))
671        (local.set $ret (call $future.read (local.get $fr) (i32.const 40)))
672        (if (i32.ne (i32.const 0 (; COMPLETED ;)) (local.get $ret)) (then (unreachable)))
673        (if (i32.ne (call $context.get) (i32.const 500)) (then (unreachable)))
674
675        (call $task.return (i32.const 42))
676        (i32.const 0 (; EXIT ;))
677      )
678
679      ;; Same as above, but for streams.
680      (func (export "run-stream") (param $sr i32) (result i32)
681        (local $ret i32)
682
683        (call $context.set (i32.const 400))
684        (local.set $ret (call $stream.read (local.get $sr) (i32.const 40) (i32.const 1)))
685        (if (i32.ne (i32.const 0x10 (; COMPLETED | 1<<4 ;)) (local.get $ret)) (then (unreachable)))
686        (if (i32.ne (call $context.get) (i32.const 500)) (then (unreachable)))
687
688        (call $task.return (i32.const 42))
689        (i32.const 0 (; EXIT ;))
690      )
691
692      (func (export "run-cb") (param i32 i32 i32) (result i32) unreachable))
693
694      (core instance $M (instantiate $m (with "" (instance
695        (export "future.read" (func $future.read))
696        (export "stream.read" (func $stream.read))
697        (export "context.set" (func $context.set))
698        (export "context.get" (func $context.get))
699        (export "task.return" (func $task.return))
700        (export "memory" (memory 1))))))
701      (func (export "run-future") async (param "future" $FT) (result u32)
702        (canon lift (core func $M "run-future") (memory $libc "memory") (realloc (func $libc "realloc"))
703          async (callback (func $M "run-cb"))
704        )
705      )
706      (func (export "run-stream") async (param "stream" $ST) (result u32)
707        (canon lift (core func $M "run-stream") (memory $libc "memory") (realloc (func $libc "realloc"))
708          async (callback (func $M "run-cb"))
709        )
710      )
711  )
712
713  (instance $Reader (instantiate $reader))
714  (instance $Writer (instantiate $writer
715    (with "reader" (instance $Reader)
716  )))
717
718  (func (export "run") (alias export $Writer "run"))
719)
720(assert_return (invoke "run") (u32.const 42))
721