A documentation-only addition for Phase −1.F of docs/archive/bootstrap-plan.html.
This is the convention the bootstrap compiler will use to talk to WASI / WASIX
syscalls that return more than a single i32.
@extern declares a single result type:
\\ @extern wasi_proc_exit (Int) -> Void # void return
\\ @extern get_arg_count () -> Int # single i32 return
But WASI syscalls like path_open return an errno and write their actual
result (the new file descriptor) into a buffer the caller supplies:
__wasi_errno_t __wasi_path_open(
__wasi_fd_t fd,
__wasi_lookupflags_t dirflags,
const char * path,
size_t path_len,
__wasi_oflags_t oflags,
__wasi_rights_t fs_rights_base,
__wasi_rights_t fs_rights_inheriting,
__wasi_fdflags_t fdflags,
__wasi_fd_t * opened_fd /* host writes here */
);A Silicon side @extern can't express the *opened_fd out-pointer in its
result type, but it doesn't need to: WebAssembly passes pointers as i32
arguments, so the out-parameter rides the input arg list.
- Declare the extern with an extra
Intarg per out-pointer. Document in a comment which arg is the out-pointer. - Allocate scratch space with
scratch_alloc(n). The helper is exported bystd.watand returns a writable i32 address. - Read the result back with
WASM::i32_load(address), or with a per-type variant (i32_load8_u,f32_load, …). - Lifetime: scratch addresses live until the next
arena_reset. Stage 0 has no reset hook (one-shot compile); Stage 1 will reset between compile passes.
# out-pointer (last arg): host writes the new fd there
\\ @extern wasi_path_open (Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Int;
\\ openFile (Int, Int) -> Int
@fn openFile path_ptr, path_len := {
fd_out := scratch_alloc(4);
wasi_path_open(
3, 0, path_ptr, path_len, # dirfd=3 (first preopen), flags=0
0, 0xFFFFFFFF, 0xFFFFFFFF, 0,
fd_out);
WASM::i32_load(fd_out) # the fd the host wrote
};
WASM 2.0 multi-value works in principle, but:
- Stage 0's IR encodes
@externresults as a single optional type (src/modules/loader.ts). - The bootstrap is small enough that one address-per-out-parameter is cheaper than threading multi-value through every layer.
- WASIX itself returns errno on the stack and writes results through out-pointers, so this convention matches the underlying syscall API directly.
Multi-return is on the post-Stage-3 wishlist; for the bootstrap, this convention is the supported path.
The conventions are tested in tests/properties/extern-outptr.property.test.ts.
The end-to-end "host actually wrote through the pointer" check belongs in
Phase 0 of the bootstrap plan (WASIX smoke test); at compile time we only
assert the plumbing is correct.