wasmtime-cli 46.0.2

Command-line interface for Wasmtime
Documentation
;;! component_model_async = true
;;! component_model_threading = true
;;! component_model_async_stackful = true
;;! component_model_more_async_builtins = true
;;! reference_types = true

;; Test task deletion in three situations, for every combination of lift/lower/(guest/host):
;; 1. An explicit thread calls task.return
;; 2. An explicit thread suspends indefinitely
;; 3. An explicit thread yield loops indefinitely
(component
    (component $C
        (core module $Memory (memory (export "mem") 1))
        (core instance $memory (instantiate $Memory))
        ;; Defines the table for the thread start functions
        (core module $libc
            (table (export "__indirect_function_table") 3 funcref))
        (core module $CM
            (import "" "mem" (memory 1))
            (import "" "task.return" (func $task-return (param i32)))
            (import "" "task.cancel" (func $task-cancel))
            (import "" "thread.new-indirect" (func $thread-new-indirect (param i32 i32) (result i32)))
            (import "" "thread.suspend" (func $thread-suspend (result i32)))
            (import "" "thread.suspend-cancellable" (func $thread-suspend-cancellable (result i32)))
            (import "" "thread.yield-to-suspended" (func $thread-yield-to-suspended (param i32) (result i32)))
            (import "" "thread.yield-to-suspended-cancellable" (func $thread-yield-to-suspended-cancellable (param i32) (result i32)))
            (import "" "thread.suspend-to" (func $thread-suspend-to (param i32) (result i32)))
            (import "" "thread.suspend-to-cancellable" (func $thread-suspend-to-cancellable (param i32) (result i32)))
            (import "" "thread.yield" (func $thread-yield (result i32)))
            (import "" "thread.yield-cancellable" (func $thread-yield-cancellable (result i32)))
            (import "" "thread.index" (func $thread-index (result i32)))
            (import "" "thread.unsuspend" (func $thread-unsuspend (param i32)))
            (import "" "waitable.join" (func $waitable.join (param i32 i32)))
            (import "" "waitable-set.new" (func $waitable-set.new (result i32)))
            (import "" "waitable-set.wait" (func $waitable-set.wait (param i32 i32) (result i32)))
            (import "libc" "__indirect_function_table" (table $indirect-function-table 3 funcref))

            ;; Indices into the function table for the thread start functions
            (global $call-return-ftbl-idx i32 (i32.const 0))
            (global $suspend-ftbl-idx i32 (i32.const 1))
            (global $yield-loop-ftbl-idx i32 (i32.const 2))

            (func $call-return (param i32)
                (call $task-return (local.get 0)))

            (func $suspend (param i32)
                (drop (call $thread-suspend)))

            (func $yield-loop (param i32)
                (loop $top
                    (drop (call $thread-yield))
                    (br $top)))

            (func (export "explicit-thread-calls-return-stackful")
                (call $thread-unsuspend
                    (call $thread-new-indirect (global.get $call-return-ftbl-idx) (i32.const 42))))

            (func (export "explicit-thread-calls-return-stackless") (result i32)
                (call $thread-unsuspend
                    (call $thread-new-indirect (global.get $call-return-ftbl-idx) (i32.const 42)))
                (i32.const 0 (; EXIT ;)))

            (func (export "cb") (param i32 i32 i32) (result i32)
                (unreachable))

            (func (export "explicit-thread-suspends-sync") (result i32)
                (call $thread-unsuspend
                    (call $thread-new-indirect (global.get $suspend-ftbl-idx) (i32.const 42)))
                (i32.const 42))

            (func (export "explicit-thread-suspends-stackful")
                (call $thread-unsuspend
                    (call $thread-new-indirect (global.get $suspend-ftbl-idx) (i32.const 42)))
                (call $task-return (i32.const 42)))

            (func (export "explicit-thread-suspends-stackless") (result i32)
                (call $thread-unsuspend
                    (call $thread-new-indirect (global.get $suspend-ftbl-idx) (i32.const 42)))
                (call $task-return (i32.const 42))
                (i32.const 0))

            (func (export "explicit-thread-yield-loops-sync") (result i32)
                (call $thread-unsuspend
                    (call $thread-new-indirect (global.get $yield-loop-ftbl-idx) (i32.const 42)))
                (i32.const 42))

            (func (export "explicit-thread-yield-loops-stackful")
                (call $thread-unsuspend
                    (call $thread-new-indirect (global.get $yield-loop-ftbl-idx) (i32.const 42)))
                (call $task-return (i32.const 42)))

            (func (export "explicit-thread-yield-loops-stackless") (result i32)
                (call $thread-unsuspend
                    (call $thread-new-indirect (global.get $suspend-ftbl-idx) (i32.const 42)))
                (call $task-return (i32.const 42))
                (i32.const 0 (; EXIT ;)))

            ;; Initialize the function table that will be used by thread.new-indirect
            (elem (table $indirect-function-table) (i32.const 0 (; call-return-ftbl-idx ;)) func $call-return)
            (elem (table $indirect-function-table) (i32.const 1 (; suspend-ftbl-idx ;)) func $suspend)
            (elem (table $indirect-function-table) (i32.const 2 (; yield-loop-ftbl-idx ;)) func $yield-loop)
        )

        ;; Instantiate the libc module to get the table
        (core instance $libc (instantiate $libc))
        ;; Get access to `thread.new-indirect` that uses the table from libc
        (core type $start-func-ty (func (param i32)))
        (alias core export $libc "__indirect_function_table" (core table $indirect-function-table))

        (core func $task-return (canon task.return (result u32)))
        (core func $task-cancel (canon task.cancel))
        (core func $thread-new-indirect
            (canon thread.new-indirect $start-func-ty (table $indirect-function-table)))
        (core func $thread-yield (canon thread.yield))
        (core func $thread-yield-cancellable (canon thread.yield cancellable))
        (core func $thread-index (canon thread.index))
        (core func $thread-yield-to-suspended (canon thread.yield-to-suspended))
        (core func $thread-yield-to-suspended-cancellable (canon thread.yield-to-suspended cancellable))
        (core func $thread-unsuspend (canon thread.unsuspend))
        (core func $thread-suspend-to (canon thread.suspend-to))
        (core func $thread-suspend-to-cancellable (canon thread.suspend-to cancellable))
        (core func $thread-suspend (canon thread.suspend))
        (core func $thread-suspend-cancellable (canon thread.suspend cancellable))
        (core func $waitable-set.new (canon waitable-set.new))
        (core func $waitable.join (canon waitable.join))
        (core func $waitable-set.wait (canon waitable-set.wait (memory $memory "mem")))

        ;; Instantiate the main module
        (core instance $cm (
            instantiate $CM
                (with "" (instance
                    (export "mem" (memory $memory "mem"))
                    (export "task.return" (func $task-return))
                    (export "task.cancel" (func $task-cancel))
                    (export "thread.new-indirect" (func $thread-new-indirect))
                    (export "thread.index" (func $thread-index))
                    (export "thread.yield-to-suspended" (func $thread-yield-to-suspended))
                    (export "thread.yield-to-suspended-cancellable" (func $thread-yield-to-suspended-cancellable))
                    (export "thread.yield" (func $thread-yield))
                    (export "thread.yield-cancellable" (func $thread-yield-cancellable))
                    (export "thread.suspend-to" (func $thread-suspend-to))
                    (export "thread.suspend-to-cancellable" (func $thread-suspend-to-cancellable))
                    (export "thread.suspend" (func $thread-suspend))
                    (export "thread.suspend-cancellable" (func $thread-suspend-cancellable))
                    (export "thread.unsuspend" (func $thread-unsuspend))
                    (export "waitable.join" (func $waitable.join))
                    (export "waitable-set.wait" (func $waitable-set.wait))
                    (export "waitable-set.new" (func $waitable-set.new))))
                (with "libc" (instance $libc))))

        (func (export "explicit-thread-calls-return-stackful") async (result u32)
            (canon lift (core func $cm "explicit-thread-calls-return-stackful") async))
        (func (export "explicit-thread-calls-return-stackless") async (result u32)
            (canon lift (core func $cm "explicit-thread-calls-return-stackless") async (callback (func $cm "cb"))))
        (func (export "explicit-thread-suspends-sync") async (result u32)
            (canon lift (core func $cm "explicit-thread-suspends-sync")))
        (func (export "explicit-thread-suspends-stackful") async (result u32)
            (canon lift (core func $cm "explicit-thread-suspends-stackful") async))
        (func (export "explicit-thread-suspends-stackless") async (result u32)
            (canon lift (core func $cm "explicit-thread-suspends-stackless") async (callback (func $cm "cb"))))
        (func (export "explicit-thread-yield-loops-sync") async (result u32)
            (canon lift (core func $cm "explicit-thread-yield-loops-sync")))
        (func (export "explicit-thread-yield-loops-stackful") async (result u32)
            (canon lift (core func $cm "explicit-thread-yield-loops-stackful") async))
        (func (export "explicit-thread-yield-loops-stackless") async (result u32)
            (canon lift (core func $cm "explicit-thread-yield-loops-stackless") async (callback (func $cm "cb"))))
    )

    (component $D
        (import "explicit-thread-calls-return-stackful" (func $explicit-thread-calls-return-stackful async (result u32)))
        (import "explicit-thread-calls-return-stackless" (func $explicit-thread-calls-return-stackless async (result u32)))
        (import "explicit-thread-suspends-sync" (func $explicit-thread-suspends-sync async (result u32)))
        (import "explicit-thread-suspends-stackful" (func $explicit-thread-suspends-stackful async (result u32)))
        (import "explicit-thread-suspends-stackless" (func $explicit-thread-suspends-stackless async (result u32)))
        (import "explicit-thread-yield-loops-sync" (func $explicit-thread-yield-loops-sync async (result u32)))
        (import "explicit-thread-yield-loops-stackful" (func $explicit-thread-yield-loops-stackful async (result u32)))
        (import "explicit-thread-yield-loops-stackless" (func $explicit-thread-yield-loops-stackless async (result u32)))

        (core module $Memory (memory (export "mem") 1))
        (core instance $memory (instantiate $Memory))
        (core module $DM
            (import "" "mem" (memory 1))
            (import "" "subtask.cancel" (func $subtask.cancel (param i32) (result i32)))
            ;; sync lowered
            (import "" "explicit-thread-calls-return-stackful" (func $explicit-thread-calls-return-stackful (result i32)))
            (import "" "explicit-thread-calls-return-stackless" (func $explicit-thread-calls-return-stackless (result i32)))
            (import "" "explicit-thread-suspends-sync" (func $explicit-thread-suspends-sync (result i32)))
            (import "" "explicit-thread-suspends-stackful" (func $explicit-thread-suspends-stackful (result i32)))
            (import "" "explicit-thread-suspends-stackless" (func $explicit-thread-suspends-stackless (result i32)))
            (import "" "explicit-thread-yield-loops-sync" (func $explicit-thread-yield-loops-sync (result i32)))
            (import "" "explicit-thread-yield-loops-stackful" (func $explicit-thread-yield-loops-stackful (result i32)))
            (import "" "explicit-thread-yield-loops-stackless" (func $explicit-thread-yield-loops-stackless (result i32)))
            ;; async lowered
            (import "" "explicit-thread-calls-return-stackful-async" (func $explicit-thread-calls-return-stackful-async (param i32) (result i32)))
            (import "" "explicit-thread-calls-return-stackless-async" (func $explicit-thread-calls-return-stackless-async (param i32) (result i32)))
            (import "" "explicit-thread-suspends-sync-async" (func $explicit-thread-suspends-sync-async (param i32) (result i32)))
            (import "" "explicit-thread-suspends-stackful-async" (func $explicit-thread-suspends-stackful-async (param i32) (result i32)))
            (import "" "explicit-thread-suspends-stackless-async" (func $explicit-thread-suspends-stackless-async (param i32) (result i32)))
            (import "" "explicit-thread-yield-loops-sync-async" (func $explicit-thread-yield-loops-sync-async (param i32) (result i32)))
            (import "" "explicit-thread-yield-loops-stackful-async" (func $explicit-thread-yield-loops-stackful-async (param i32) (result i32)))
            (import "" "explicit-thread-yield-loops-stackless-async" (func $explicit-thread-yield-loops-stackless-async (param i32) (result i32)))
            (import "" "waitable.join" (func $waitable.join (param i32 i32)))
            (import "" "waitable-set.new" (func $waitable-set.new (result i32)))
            (import "" "waitable-set.wait" (func $waitable-set.wait (param i32 i32) (result i32)))
            (import "" "thread.yield" (func $thread-yield (result i32)))

            (func $check (param i32)
                (if (i32.ne (local.get 0) (i32.const 42))
                    (then unreachable))
            )

            (func $check-async (param i32)
                (local $retp i32) (local $ws i32) (local $ws-retp i32)
                (local.set $retp (i32.const 8))
                (local.set $ws-retp (i32.const 16))
                (local.set $ws (call $waitable-set.new))

                (if (i32.eq (i32.and (local.get 0) (i32.const 0xF)) (i32.const 2 (; RETURNED ;)))
                    (then (call $check (i32.load (local.get $retp))))
                    (else
                        (call $waitable.join (i32.shr_u (local.get 0) (i32.const 4)) (local.get $ws))
                        (drop (call $waitable-set.wait (local.get $ws) (local.get $ws-retp)))
                        (call $check (i32.load (local.get $retp)))))
            )

            (func $run (export "run") (result i32)
                (local $retp i32)
                (local.set $retp (i32.const 8))
                (call $check (call $explicit-thread-calls-return-stackless))
                (call $check (call $explicit-thread-calls-return-stackful))
                (call $check (call $explicit-thread-suspends-sync))
                (call $check (call $explicit-thread-suspends-stackful))
                (call $check (call $explicit-thread-suspends-stackless))
                (call $check (call $explicit-thread-yield-loops-sync))
                (call $check (call $explicit-thread-yield-loops-stackful))
                (call $check (call $explicit-thread-yield-loops-stackless))

                (call $check-async (call $explicit-thread-calls-return-stackless-async (local.get $retp)))
                (call $check-async (call $explicit-thread-calls-return-stackful-async (local.get $retp)))
                (call $check-async (call $explicit-thread-suspends-sync-async (local.get $retp)))
                (call $check-async (call $explicit-thread-suspends-stackful-async (local.get $retp)))
                (call $check-async (call $explicit-thread-suspends-stackless-async (local.get $retp)))
                (call $check-async (call $explicit-thread-yield-loops-sync-async (local.get $retp)))
                (call $check-async (call $explicit-thread-yield-loops-stackful-async (local.get $retp)))
                (call $check-async (call $explicit-thread-yield-loops-stackless-async (local.get $retp)))

                (i32.const 42)
            )
        )

        (core func $waitable-set.new (canon waitable-set.new))
        (core func $waitable-set.wait (canon waitable-set.wait (memory $memory "mem")))
        (core func $waitable.join (canon waitable.join))
        (core func $subtask.cancel (canon subtask.cancel async))
        (core func $thread.yield (canon thread.yield))
        ;; sync lowered
        (canon lower (func $explicit-thread-calls-return-stackful) (memory $memory "mem") (core func $explicit-thread-calls-return-stackful'))
        (canon lower (func $explicit-thread-calls-return-stackless) (memory $memory "mem") (core func $explicit-thread-calls-return-stackless'))
        (canon lower (func $explicit-thread-suspends-sync) (memory $memory "mem") (core func $explicit-thread-suspends-sync'))
        (canon lower (func $explicit-thread-suspends-stackful) (memory $memory "mem") (core func $explicit-thread-suspends-stackful'))
        (canon lower (func $explicit-thread-suspends-stackless) (memory $memory "mem") (core func $explicit-thread-suspends-stackless'))
        (canon lower (func $explicit-thread-yield-loops-sync) (memory $memory "mem") (core func $explicit-thread-yield-loops-sync'))
        (canon lower (func $explicit-thread-yield-loops-stackful) (memory $memory "mem") (core func $explicit-thread-yield-loops-stackful'))
        (canon lower (func $explicit-thread-yield-loops-stackless) (memory $memory "mem") (core func $explicit-thread-yield-loops-stackless'))
        ;; async lowered
        (canon lower (func $explicit-thread-calls-return-stackful) async (memory $memory "mem") (core func $explicit-thread-calls-return-stackful-async'))
        (canon lower (func $explicit-thread-calls-return-stackless) async (memory $memory "mem") (core func $explicit-thread-calls-return-stackless-async'))
        (canon lower (func $explicit-thread-suspends-sync) async (memory $memory "mem") (core func $explicit-thread-suspends-sync-async'))
        (canon lower (func $explicit-thread-suspends-stackful) async (memory $memory "mem") (core func $explicit-thread-suspends-stackful-async'))
        (canon lower (func $explicit-thread-suspends-stackless) async (memory $memory "mem") (core func $explicit-thread-suspends-stackless-async'))
        (canon lower (func $explicit-thread-yield-loops-sync) async (memory $memory "mem") (core func $explicit-thread-yield-loops-sync-async'))
        (canon lower (func $explicit-thread-yield-loops-stackful) async (memory $memory "mem") (core func $explicit-thread-yield-loops-stackful-async'))
        (canon lower (func $explicit-thread-yield-loops-stackless) async (memory $memory "mem") (core func $explicit-thread-yield-loops-stackless-async'))
        (core instance $dm (instantiate $DM (with "" (instance
            (export "mem" (memory $memory "mem"))
            (export "explicit-thread-calls-return-stackful" (func $explicit-thread-calls-return-stackful'))
            (export "explicit-thread-calls-return-stackless" (func $explicit-thread-calls-return-stackless'))
            (export "explicit-thread-suspends-sync" (func $explicit-thread-suspends-sync'))
            (export "explicit-thread-suspends-stackful" (func $explicit-thread-suspends-stackful'))
            (export "explicit-thread-suspends-stackless" (func $explicit-thread-suspends-stackless'))
            (export "explicit-thread-yield-loops-sync" (func $explicit-thread-yield-loops-sync'))
            (export "explicit-thread-yield-loops-stackful" (func $explicit-thread-yield-loops-stackful'))
            (export "explicit-thread-yield-loops-stackless" (func $explicit-thread-yield-loops-stackless'))
            (export "explicit-thread-calls-return-stackful-async" (func $explicit-thread-calls-return-stackful-async'))
            (export "explicit-thread-calls-return-stackless-async" (func $explicit-thread-calls-return-stackless-async'))
            (export "explicit-thread-suspends-sync-async" (func $explicit-thread-suspends-sync-async'))
            (export "explicit-thread-suspends-stackful-async" (func $explicit-thread-suspends-stackful-async'))
            (export "explicit-thread-suspends-stackless-async" (func $explicit-thread-suspends-stackless-async'))
            (export "explicit-thread-yield-loops-sync-async" (func $explicit-thread-yield-loops-sync-async'))
            (export "explicit-thread-yield-loops-stackful-async" (func $explicit-thread-yield-loops-stackful-async'))
            (export "explicit-thread-yield-loops-stackless-async" (func $explicit-thread-yield-loops-stackless-async'))
            (export "waitable.join" (func $waitable.join))
            (export "waitable-set.new" (func $waitable-set.new))
            (export "waitable-set.wait" (func $waitable-set.wait))
            (export "subtask.cancel" (func $subtask.cancel))
            (export "thread.yield" (func $thread.yield))
        ))))
        (func (export "run") async (result u32) (canon lift (core func $dm "run")))
    )

    (instance $c (instantiate $C))
    (instance $d (instantiate $D
        (with "explicit-thread-calls-return-stackful" (func $c "explicit-thread-calls-return-stackful"))
        (with "explicit-thread-calls-return-stackless" (func $c "explicit-thread-calls-return-stackless"))
        (with "explicit-thread-suspends-sync" (func $c "explicit-thread-suspends-sync"))
        (with "explicit-thread-suspends-stackful" (func $c "explicit-thread-suspends-stackful"))
        (with "explicit-thread-suspends-stackless" (func $c "explicit-thread-suspends-stackless"))
        (with "explicit-thread-yield-loops-sync" (func $c "explicit-thread-yield-loops-sync"))
        (with "explicit-thread-yield-loops-stackful" (func $c "explicit-thread-yield-loops-stackful"))
        (with "explicit-thread-yield-loops-stackless" (func $c "explicit-thread-yield-loops-stackless"))
    ))
  (func (export "run") (alias export $d "run"))
  (func (export "explicit-thread-calls-return-stackful") (alias export $c "explicit-thread-calls-return-stackful"))
  (func (export "explicit-thread-calls-return-stackless") (alias export $c "explicit-thread-calls-return-stackless"))
  (func (export "explicit-thread-suspends-sync") (alias export $c "explicit-thread-suspends-sync"))
  (func (export "explicit-thread-suspends-stackful") (alias export $c "explicit-thread-suspends-stackful"))
  (func (export "explicit-thread-suspends-stackless") (alias export $c "explicit-thread-suspends-stackless"))
  (func (export "explicit-thread-yield-loops-sync") (alias export $c "explicit-thread-yield-loops-sync"))
  (func (export "explicit-thread-yield-loops-stackful") (alias export $c "explicit-thread-yield-loops-stackful"))
  (func (export "explicit-thread-yield-loops-stackless") (alias export $c "explicit-thread-yield-loops-stackless"))
)

(assert_return (invoke "run") (u32.const 42))
(assert_return (invoke "explicit-thread-calls-return-stackful") (u32.const 42))
(assert_return (invoke "explicit-thread-calls-return-stackless") (u32.const 42))
(assert_return (invoke "explicit-thread-suspends-sync") (u32.const 42))
(assert_return (invoke "explicit-thread-suspends-stackful") (u32.const 42))
(assert_return (invoke "explicit-thread-suspends-stackless") (u32.const 42))
(assert_return (invoke "explicit-thread-yield-loops-sync") (u32.const 42))
(assert_return (invoke "explicit-thread-yield-loops-stackful") (u32.const 42))
(assert_return (invoke "explicit-thread-yield-loops-stackless") (u32.const 42))