diff --git a/wasm/CHANGELOG.md b/wasm/CHANGELOG.md index 724f5edd43eb..3f5f9f4ca94f 100644 --- a/wasm/CHANGELOG.md +++ b/wasm/CHANGELOG.md @@ -9,6 +9,7 @@ This changelog summarizes major changes to the WebAssembly engine implemented in ## Version 24.1.0 * Implemented the [SIMD](https://github.com/WebAssembly/simd) proposal. This feature is enabled by default and can be disabled with the option `--wasm.SIMD=false`. +* Added limited support for `fd_advise` in `wasi_snapshot_preview1`. ## Version 23.1.0 diff --git a/wasm/mx.wasm/mx_wasm.py b/wasm/mx.wasm/mx_wasm.py index 5758773d7eb8..0c8712124ebf 100644 --- a/wasm/mx.wasm/mx_wasm.py +++ b/wasm/mx.wasm/mx_wasm.py @@ -630,7 +630,7 @@ def emscripten_init(args): @mx.command(_suite.name, "wasm") def wasm(args, **kwargs): """Run a WebAssembly program.""" - vmArgs, wasmArgs = mx.extract_VM_args(args, useDoubleDash=False, defaultAllVMArgs=False) + vmArgs, wasmArgs = mx.extract_VM_args(args, useDoubleDash=True, defaultAllVMArgs=False) path_args = mx.get_runtime_jvm_args([ "TRUFFLE_API", "org.graalvm.wasm", diff --git a/wasm/src/org.graalvm.wasm.test/src/test/wasi/fd_advise-file.opts b/wasm/src/org.graalvm.wasm.test/src/test/wasi/fd_advise-file.opts new file mode 100644 index 000000000000..7bfd1a84a622 --- /dev/null +++ b/wasm/src/org.graalvm.wasm.test/src/test/wasi/fd_advise-file.opts @@ -0,0 +1 @@ +enable-io=true diff --git a/wasm/src/org.graalvm.wasm.test/src/test/wasi/fd_advise-file.result b/wasm/src/org.graalvm.wasm.test/src/test/wasi/fd_advise-file.result new file mode 100644 index 000000000000..8a50673d0631 --- /dev/null +++ b/wasm/src/org.graalvm.wasm.test/src/test/wasi/fd_advise-file.result @@ -0,0 +1 @@ +int 0 \ No newline at end of file diff --git a/wasm/src/org.graalvm.wasm.test/src/test/wasi/fd_advise-file.wat b/wasm/src/org.graalvm.wasm.test/src/test/wasi/fd_advise-file.wat new file mode 100644 index 000000000000..e19f0fcc3f92 --- /dev/null +++ b/wasm/src/org.graalvm.wasm.test/src/test/wasi/fd_advise-file.wat @@ -0,0 +1,185 @@ +;; +;; Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +;; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +;; +;; The Universal Permissive License (UPL), Version 1.0 +;; +;; Subject to the condition set forth below, permission is hereby granted to any +;; person obtaining a copy of this software, associated documentation and/or +;; data (collectively the "Software"), free of charge and under any and all +;; copyright rights in the Software, and any and all patent rights owned or +;; freely licensable by each licensor hereunder covering either (i) the +;; unmodified Software as contributed to or provided by such licensor, or (ii) +;; the Larger Works (as defined below), to deal in both +;; +;; (a) the Software, and +;; +;; (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +;; one is included with the Software each a "Larger Work" to which the Software +;; is contributed by such licensors), +;; +;; without restriction, including without limitation the rights to copy, create +;; derivative works of, display, perform, and distribute the Software and make, +;; use, sell, offer for sale, import, export, have made, and have sold the +;; Software and the Larger Work(s), and to sublicense the foregoing rights on +;; either these or other terms. +;; +;; This license is subject to the following condition: +;; +;; The above copyright notice and either this complete permission notice or at a +;; minimum a reference to the UPL must be included in all copies or substantial +;; portions of the Software. +;; +;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +;; SOFTWARE. +;; + +(module + (import "wasi_snapshot_preview1" "path_open" (func $path_open (param i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i32))) + (import "wasi_snapshot_preview1" "fd_advise" (func $fd_advise (param i32 i64 i64 i32) (result i32))) + (import "wasi_snapshot_preview1" "fd_close" (func $fd_close (param i32) (result i32))) + + (memory 1) + + (data (i32.const 0) "file.txt") + + (export "memory" (memory 0)) + + ;; Pre-opened temporary directory fd + (global $directory_fd i32 (i32.const 3)) + + ;; Memory location of file path + (global $file_path_address i32 (i32.const 0)) + (global $file_path_length i32 (i32.const 8)) + + ;; Address of opened file fd + (global $file_fd_address i32 (i32.const 12)) + + ;; Rights for path_open + (global $all_rights i64 (i64.const 536870911)) + (global $advise_right i64 (i64.const 128)) + + ;; Advice for fd_advise + (global $sequential_access_advice i32 (i32.const 1)) + + ;; Errno codes + (global $errno_inval i32 (i32.const 28)) + (global $errno_badf i32 (i32.const 8)) + (global $errno_notcapable i32 (i32.const 76)) + + (func (export "_main") (result i32) (local $ret i32) + ;; Open file "file.txt" in pre-opened directory + (local.set $ret + (call $path_open + (global.get $directory_fd) ;; pre-opened "test" directory fd + (i32.const 0) ;; dirflags + (global.get $file_path_address) ;; pointer to path "file.txt" + (global.get $file_path_length) ;; path length + (i32.const 0) ;; oflags + (global.get $all_rights) ;; rights base (all rights set) + (global.get $all_rights) ;; rights inherting (all rights set) + (i32.const 0) ;; fdflags + (global.get $file_fd_address) ;; fd address + ) + ) + ;; Exit in case of error + (if (i32.ne (local.get $ret) (i32.const 0)) (then (return (local.get $ret)))) + + ;; Valid advice + (local.set $ret + (call $fd_advise + (i32.load (global.get $file_fd_address)) ;; "file.txt" fd + (i64.const 0) ;; offset of advised region + (i64.const 0) ;; length of advised region + (global.get $sequential_access_advice) ;; sequential access advice + ) + ) + ;; Exit in case of error + (if (i32.ne (local.get $ret) (i32.const 0)) (then (return (local.get $ret)))) + + ;; Invalid advice + (local.set $ret + (call $fd_advise + (i32.load (global.get $file_fd_address)) ;; "file.txt" fd + (i64.const 0) ;; offset of advised region + (i64.const 0) ;; length of advised region + (i32.const 42) ;; invalid advice + ) + ) + ;; Check that error code is inval + (if (i32.ne (local.get $ret) (global.get $errno_inval)) (then (return (i32.const -1)))) + + ;; Invalid length of advised region + (local.set $ret + (call $fd_advise + (i32.load (global.get $file_fd_address)) ;; "file.txt" fd + (i64.const 1) ;; offset of advised region + (i64.const -1) ;; length of advised region (must be non-negative) + (global.get $sequential_access_advice) ;; sequential access advice + ) + ) + ;; Check that error code is inval + (if (i32.ne (local.get $ret) (global.get $errno_inval)) (then (return (i32.const -2)))) + + ;; Invalid file descriptor + (local.set $ret + (call $fd_advise + (i32.add (i32.load (global.get $file_fd_address)) (i32.const 1)) ;; invalid fd + (i64.const 0) ;; offset of advised region + (i64.const 0) ;; length of advised region + (global.get $sequential_access_advice) ;; sequential access advice + ) + ) + ;; Check that error code is badf + (if (i32.ne (local.get $ret) (global.get $errno_badf)) (then (return (i32.const -3)))) + + ;; Free opened file + (local.set $ret (call $fd_close (i32.load (global.get $file_fd_address)))) + ;; Exit in case of error + (if (i32.ne (local.get $ret) (i32.const 0)) (then (return (local.get $ret)))) + + ;; Open file "file.txt" in pre-opened directory 3 without advise capabilities + (local.set $ret + (call $path_open + (global.get $directory_fd) ;; pre-opened "test" directory fd + (i32.const 0) ;; dirflags + (global.get $file_path_address) ;; pointer to path "file.txt" + (global.get $file_path_length) ;; path length + (i32.const 0) ;; oflags + (i64.sub (global.get $all_rights) (global.get $advise_right)) ;; rights base (all rights set except for fd_advise) + (i64.sub (global.get $all_rights) (global.get $advise_right)) ;; rights inheriting (all rights set except for fd_advise) + (i32.const 0) ;; fdflags + (global.get $file_fd_address) ;; fd address + ) + ) + ;; Exit in case of error + (if (i32.ne (local.get $ret) (i32.const 0)) (then (return (local.get $ret)))) + + ;; Insufficient capabilities for advise + (local.set $ret + (call $fd_advise + (i32.load (global.get $file_fd_address)) ;; "file.txt" fd without advise rights + (i64.const 0) ;; offset of advised region + (i64.const 0) ;; length of advised region + (global.get $sequential_access_advice) ;; sequential access advice + ) + ) + ;; Check that error code is notcapable + (if (i32.ne (local.get $ret) (global.get $errno_notcapable)) (then (return (i32.const -4)))) + + ;; Free opened file + (local.set $ret (call $fd_close (i32.load (global.get $file_fd_address)))) + ;; Exit in case of error + (if (i32.ne (local.get $ret) (i32.const 0)) (then (return (local.get $ret)))) + + ;; Clear random fd number so that this test is deterministic + (i32.store (global.get $file_fd_address) (i32.const 0)) + ;; Success + (i32.const 0) + ) +) \ No newline at end of file diff --git a/wasm/src/org.graalvm.wasm.test/src/test/wasi/wasm_test_index b/wasm/src/org.graalvm.wasm.test/src/test/wasi/wasm_test_index index 949088c17509..06f3942e3d64 100644 --- a/wasm/src/org.graalvm.wasm.test/src/test/wasi/wasm_test_index +++ b/wasm/src/org.graalvm.wasm.test/src/test/wasi/wasm_test_index @@ -3,6 +3,7 @@ args-sizes-get proc-exit environ-get environ-sizes-get +fd_advise-file fd_prestat_get fd_prestat_dir_name fd_read-stdin diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/WasmMemory.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/WasmMemory.java index 74da7871ec57..dd8cc63464fc 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/WasmMemory.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/WasmMemory.java @@ -519,7 +519,7 @@ public final String readString(int startOffset, int length, Node node) { * @param string the string to write * @param offset memory index where to write the string * @param length the maximum number of bytes to write, including the trailing null character - * @return the number of bytes written, including the trailing null character + * @return the number of bytes written */ @CompilerDirectives.TruffleBoundary public final int writeString(Node node, String string, int offset, int length) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdAdviseNode.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdAdviseNode.java new file mode 100644 index 000000000000..01b57dc67487 --- /dev/null +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdAdviseNode.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.graalvm.wasm.predefined.wasi; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.frame.VirtualFrame; +import org.graalvm.wasm.WasmArguments; +import org.graalvm.wasm.WasmContext; +import org.graalvm.wasm.WasmInstance; +import org.graalvm.wasm.WasmLanguage; +import org.graalvm.wasm.WasmModule; +import org.graalvm.wasm.predefined.WasmBuiltinRootNode; +import org.graalvm.wasm.predefined.wasi.fd.Fd; +import org.graalvm.wasm.predefined.wasi.types.Advice; +import org.graalvm.wasm.predefined.wasi.types.Errno; + +public class WasiFdAdviseNode extends WasmBuiltinRootNode { + + public WasiFdAdviseNode(WasmLanguage language, WasmModule module) { + super(language, module); + } + + @Override + public Object executeWithContext(VirtualFrame frame, WasmContext context, WasmInstance instance) { + final Object[] args = frame.getArguments(); + return fdAdvise(context, (int) WasmArguments.getArgument(args, 0), + (long) WasmArguments.getArgument(args, 1), + (long) WasmArguments.getArgument(args, 2), + (int) WasmArguments.getArgument(args, 3)); + } + + @TruffleBoundary + private static int fdAdvise(WasmContext context, int fd, long offset, long length, int adviceValue) { + final Fd handle = context.fdManager().get(fd); + if (handle == null) { + return Errno.Badf.ordinal(); + } + if (adviceValue < 0 || adviceValue >= Advice.values().length) { + return Errno.Inval.ordinal(); + } + final Advice advice = Advice.values()[adviceValue]; + if (length < 0) { + return Errno.Inval.ordinal(); + } + return handle.advise(offset, length, advice).ordinal(); + } + + @Override + public String builtinNodeName() { + return "__wasi_fd_advise"; + } +} diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdCloseNode.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdCloseNode.java index a21f2f937dce..27b504092874 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdCloseNode.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdCloseNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -84,7 +84,7 @@ private static int fdClose(WasmContext context, int fd) { @Override public String builtinNodeName() { - return "___wasi_fd_close"; + return "__wasi_fd_close"; } } diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdFilestatGetNode.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdFilestatGetNode.java index 259326f3927b..f616a01f6854 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdFilestatGetNode.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdFilestatGetNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -76,7 +76,7 @@ private int fdFilestatGet(WasmContext context, WasmMemory memory, int fd, int bu @Override public String builtinNodeName() { - return "___wasi_fd_filestat_get"; + return "__wasi_fd_filestat_get"; } } diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdPrestatDirNameNode.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdPrestatDirNameNode.java index 9475a60c3b0f..aa311081148b 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdPrestatDirNameNode.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdPrestatDirNameNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -76,7 +76,7 @@ private int fdPrestatDirName(WasmContext context, WasmMemory memory, int fd, int @Override public String builtinNodeName() { - return "___wasi_fd_prestat_dir_name"; + return "__wasi_fd_prestat_dir_name"; } } diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdPrestatGetNode.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdPrestatGetNode.java index 71315ffbb307..ac6e567fe344 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdPrestatGetNode.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdPrestatGetNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -76,7 +76,7 @@ private int fdPrestatGet(WasmContext context, WasmMemory memory, int fd, int buf @Override public String builtinNodeName() { - return "___wasi_fd_prestat_get"; + return "__wasi_fd_prestat_get"; } } diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdSeekNode.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdSeekNode.java index 20ce92102ecd..9cb642347453 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdSeekNode.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdSeekNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -81,7 +81,7 @@ private int fdSeek(WasmContext context, WasmMemory memory, int fd, long offset, @Override public String builtinNodeName() { - return "___wasi_fd_seek"; + return "__wasi_fd_seek"; } } diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdWriteNode.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdWriteNode.java index 69c95bc4ab8f..d1bc8c60122e 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdWriteNode.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiFdWriteNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -80,7 +80,7 @@ private int fdWrite(WasmContext context, WasmMemory memory, int fd, int iov, int @Override public String builtinNodeName() { - return "___wasi_fd_write"; + return "__wasi_fd_write"; } } diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiModule.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiModule.java index ee22298f1b8b..2003961150a0 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiModule.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiModule.java @@ -50,8 +50,89 @@ import org.graalvm.wasm.WasmModule; import org.graalvm.wasm.predefined.BuiltinModule; +@SuppressWarnings("unused") public final class WasiModule extends BuiltinModule { + // The WASI preview1 module's API is expressed using an IDL called witx. witx uses a C-like type + // system which is then mapped onto WebAssembly's core types. The following constants give first + // the mappings from witx types to WebAssembly types and then they use those witx types to + // define the WASI types used in the signature of the WASI module. + + // (@witx pointer) is lowered to i32 + private static final byte POINTER_TYPE = I32_TYPE; + // (@witx const_pointer) is lowered to i32 + private static final byte CONST_POINTER_TYPE = I32_TYPE; + // (record) arguments are lowered to i32 addresses unless there is a flags representation + private static final byte RECORD_TYPE = I32_TYPE; + // (union) arguments are lowered to i32 addresses unless they are simple enums + private static final byte UNION_TYPE = I32_TYPE; + // (handle) arguments are lowered to i32 values + private static final byte HANDLE_TYPE = I32_TYPE; + // (list) arguments are lowered to an address (i32) argument and a length (i32) argument + private static final byte LIST_ADDRESS_TYPE = I32_TYPE; + private static final byte LIST_LENGTH_TYPE = I32_TYPE; + // (string) arguments are lowered the same way as (list) arguments + private static final byte STRING_ADDRESS_TYPE = LIST_ADDRESS_TYPE; + private static final byte STRING_LENGTH_TYPE = LIST_LENGTH_TYPE; + private static final byte U8_TYPE = I32_TYPE; + private static final byte U16_TYPE = I32_TYPE; + private static final byte U32_TYPE = I32_TYPE; + private static final byte U64_TYPE = I64_TYPE; + private static final byte S64_TYPE = I64_TYPE; + // (result $error (expected X (error $errno))) return values are implemented by returning a + // value of type $errno and accepting as arguments pointers for writing any elements of the + // expected return value X + private static final byte RETURN_VALUE_ADDRESS_TYPE = I32_TYPE; + + private static final byte SIZE_TYPE = U32_TYPE; // u32 + private static final byte FILESIZE_TYPE = U64_TYPE; // u64 + private static final byte TIMESTAMP_TYPE = U64_TYPE; // u64 + private static final byte CLOCKID_TYPE = U32_TYPE; // (enum (@witx tag u32)) + private static final byte ERRNO_TYPE = U16_TYPE; // (enum (@witx tag u16)) + private static final byte RIGHTS_TYPE = U64_TYPE; // (flags (@witx repr u64)) + private static final byte FD_TYPE = HANDLE_TYPE; // (handle) + private static final byte IOVEC_TYPE = RECORD_TYPE; // (record) + private static final byte CIOVEC_TYPE = RECORD_TYPE; // (record) + private static final byte IOVEC_ARRAY_ADDRESS_TYPE = LIST_ADDRESS_TYPE; // (list) + private static final byte IOVEC_ARRAY_LENGTH_TYPE = LIST_LENGTH_TYPE; // (list) + private static final byte CIOVEC_ARRAY_ADDRESS_TYPE = LIST_ADDRESS_TYPE; // (list) + private static final byte CIOVEC_ARRAY_LENGTH_TYPE = LIST_LENGTH_TYPE; // (list) + private static final byte FILEDELTA_TYPE = S64_TYPE; // s64 + private static final byte WHENCE_TYPE = U8_TYPE; // (enum (@witx tag u8)) + private static final byte DIRCOOKIE_TYPE = U64_TYPE; // u64 + private static final byte DIRNAMLEN_TYPE = U32_TYPE; // u32 + private static final byte INODE_TYPE = U64_TYPE; // u64 + private static final byte FILETYPE_TYPE = U8_TYPE; // (enum (@witx tag u8)) + private static final byte DIRENT_TYPE = RECORD_TYPE; // (record) + private static final byte ADVICE_TYPE = U8_TYPE; // (enum (@witx tag u8)) + private static final byte FDFLAGS_TYPE = U16_TYPE; // (flags (@witx repr u16)) + private static final byte FDSTAT_TYPE = RECORD_TYPE; // (record) + private static final byte DEVICE_TYPE = U64_TYPE; // u64 + private static final byte FSTFLAGS_TYPE = U16_TYPE; // (flags (@witx repr u16)) + private static final byte LOOKUPFLAGS_TYPE = U32_TYPE; // (flags (@witx repr u32)) + private static final byte OFLAGS_TYPE = U16_TYPE; // (flags (@witx repr u16)) + private static final byte LINKCOUNT_TYPE = U64_TYPE; // u64 + private static final byte FILESTAT_TYPE = RECORD_TYPE; // (record) + private static final byte USERDATA_TYPE = U64_TYPE; // u64 + private static final byte EVENTTYPE_TYPE = U8_TYPE; // (enum (@witx tag u8)) + private static final byte EVENTRWFLAGS_TYPE = U16_TYPE; // (flags (@witx repr u16)) + private static final byte EVENT_FD_READWRITE_TYPE = RECORD_TYPE; // (record) + private static final byte EVENT_TYPE = RECORD_TYPE; // (record) + private static final byte SUBCLOCKFLAGS_TYPE = U16_TYPE; // (flags (@witx repr u16)) + private static final byte SUBSCRIPTION_CLOCK_TYPE = RECORD_TYPE; // (record) + private static final byte SUBSCRIPTION_FD_READWRITE_TYPE = RECORD_TYPE; // (record) + private static final byte SUBSCRIPTION_U_TYPE = UNION_TYPE; // (union) + private static final byte SUBSCRIPTION_TYPE = RECORD_TYPE; // (record) + private static final byte EXITCODE_TYPE = U32_TYPE; // u32 + private static final byte SIGNAL_TYPE = U8_TYPE; // (enum (@witx tag u8)) + private static final byte RIFLAGS_TYPE = U16_TYPE; // (flags (@witx repr u16)) + private static final byte ROFLAGS_TYPE = U16_TYPE; // (flags (@witx repr u16)) + private static final byte SIFLAGS_TYPE = U16_TYPE; // u16 + private static final byte SDFLAGS_TYPE = U8_TYPE; // (flags (@witx repr u8)) + private static final byte PREOPENTYPE_TYPE = U8_TYPE; // (enum (@witx tag u8)) + private static final byte PRESTAT_DIR_TYPE = RECORD_TYPE; // (record) + private static final byte PRESTAT_TYPE = UNION_TYPE; // (union) + @Override protected WasmModule createModule(WasmLanguage language, WasmContext context, String name) { WasmModule module = WasmModule.createBuiltin(name); @@ -60,59 +141,77 @@ protected WasmModule createModule(WasmLanguage language, WasmContext context, St } else { importMemory(context, module, "main", "memory", 0, MAX_MEMORY_DECLARATION_SIZE, false, false); } - defineFunction(context, module, "args_get", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiArgsGetNode(language, module)); - defineFunction(context, module, "args_sizes_get", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiArgsSizesGetNode(language, module)); - defineFunction(context, module, "environ_get", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiEnvironGetNode(language, module)); - defineFunction(context, module, "environ_sizes_get", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiEnvironSizesGetNode(language, module)); - defineFunction(context, module, "clock_res_get", types(I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_clock_res_get")); - defineFunction(context, module, "clock_time_get", types(I32_TYPE, I64_TYPE, I32_TYPE), types(I32_TYPE), new WasiClockTimeGetNode(language, module)); - defineFunction(context, module, "fd_advise", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_advise")); - defineFunction(context, module, "fd_allocate", types(I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_allocate")); - defineFunction(context, module, "fd_close", types(I32_TYPE), types(I32_TYPE), new WasiFdCloseNode(language, module)); - defineFunction(context, module, "fd_datasync", types(I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_datasync")); - defineFunction(context, module, "fd_fdstat_get", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiFdFdstatGetNode(language, module)); - defineFunction(context, module, "fd_fdstat_set_flags", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiFdFdstatSetFlagsNode(language, module)); - defineFunction(context, module, "fd_fdstat_set_rights", types(I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_fdstat_set_rights")); - defineFunction(context, module, "fd_filestat_get", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiFdFilestatGetNode(language, module)); - defineFunction(context, module, "fd_filestat_set_size", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_filestat_set_size")); - defineFunction(context, module, "fd_filestat_set_times", types(I32_TYPE, I64_TYPE, I64_TYPE, I32_TYPE), types(I32_TYPE), new WasiFdFilestatSetTimesNode(language, module)); - defineFunction(context, module, "fd_pread", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_pread")); - defineFunction(context, module, "fd_prestat_get", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiFdPrestatGetNode(language, module)); - defineFunction(context, module, "fd_prestat_dir_name", types(I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiFdPrestatDirNameNode(language, module)); - defineFunction(context, module, "fd_pwrite", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_pwrite")); - defineFunction(context, module, "fd_read", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiFdReadNode(language, module)); - defineFunction(context, module, "fd_readdir", types(I32_TYPE, I32_TYPE, I32_TYPE, I64_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_readdir")); - defineFunction(context, module, "fd_renumber", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_renumber")); - defineFunction(context, module, "fd_seek", types(I32_TYPE, I64_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiFdSeekNode(language, module)); - defineFunction(context, module, "fd_sync", types(I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_sync")); - defineFunction(context, module, "fd_tell", types(I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_tell")); - defineFunction(context, module, "fd_write", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiFdWriteNode(language, module)); - defineFunction(context, module, "path_create_directory", types(I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiPathCreateDirectoryNode(language, module)); - defineFunction(context, module, "path_filestat_get", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiPathFileStatGetNode(language, module)); - defineFunction(context, module, "path_filestat_set_times", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE, I64_TYPE, I64_TYPE, I32_TYPE), types(I32_TYPE), + + defineFunction(context, module, "args_get", types(POINTER_TYPE, POINTER_TYPE), types(ERRNO_TYPE), new WasiArgsGetNode(language, module)); + defineFunction(context, module, "args_sizes_get", types(RETURN_VALUE_ADDRESS_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), new WasiArgsSizesGetNode(language, module)); + defineFunction(context, module, "environ_get", types(POINTER_TYPE, POINTER_TYPE), types(ERRNO_TYPE), new WasiEnvironGetNode(language, module)); + defineFunction(context, module, "environ_sizes_get", types(RETURN_VALUE_ADDRESS_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), new WasiEnvironSizesGetNode(language, module)); + defineFunction(context, module, "clock_res_get", types(CLOCKID_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_clock_res_get")); + defineFunction(context, module, "clock_time_get", types(CLOCKID_TYPE, TIMESTAMP_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), new WasiClockTimeGetNode(language, module)); + defineFunction(context, module, "fd_advise", types(FD_TYPE, FILESIZE_TYPE, FILESIZE_TYPE, ADVICE_TYPE), types(ERRNO_TYPE), + new WasiFdAdviseNode(language, module)); + defineFunction(context, module, "fd_allocate", types(FD_TYPE, FILESIZE_TYPE, FILESIZE_TYPE), types(ERRNO_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_allocate")); + defineFunction(context, module, "fd_close", types(FD_TYPE), types(ERRNO_TYPE), new WasiFdCloseNode(language, module)); + defineFunction(context, module, "fd_datasync", types(FD_TYPE), types(ERRNO_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_datasync")); + defineFunction(context, module, "fd_fdstat_get", types(FD_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), new WasiFdFdstatGetNode(language, module)); + defineFunction(context, module, "fd_fdstat_set_flags", types(FD_TYPE, FDFLAGS_TYPE), types(ERRNO_TYPE), new WasiFdFdstatSetFlagsNode(language, module)); + defineFunction(context, module, "fd_fdstat_set_rights", types(FD_TYPE, RIGHTS_TYPE, RIGHTS_TYPE), types(ERRNO_TYPE), + new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_fdstat_set_rights")); + defineFunction(context, module, "fd_filestat_get", types(FD_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), new WasiFdFilestatGetNode(language, module)); + defineFunction(context, module, "fd_filestat_set_size", types(FD_TYPE, FILESIZE_TYPE), types(ERRNO_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_filestat_set_size")); + defineFunction(context, module, "fd_filestat_set_times", types(FD_TYPE, TIMESTAMP_TYPE, TIMESTAMP_TYPE, FSTFLAGS_TYPE), types(ERRNO_TYPE), new WasiFdFilestatSetTimesNode(language, module)); + defineFunction(context, module, "fd_pread", types(FD_TYPE, IOVEC_ARRAY_ADDRESS_TYPE, IOVEC_ARRAY_LENGTH_TYPE, FILESIZE_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), + new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_pread")); + defineFunction(context, module, "fd_prestat_get", types(FD_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), new WasiFdPrestatGetNode(language, module)); + defineFunction(context, module, "fd_prestat_dir_name", types(FD_TYPE, POINTER_TYPE, SIZE_TYPE), types(ERRNO_TYPE), new WasiFdPrestatDirNameNode(language, module)); + defineFunction(context, module, "fd_pwrite", types(FD_TYPE, CIOVEC_ARRAY_ADDRESS_TYPE, CIOVEC_ARRAY_LENGTH_TYPE, FILESIZE_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), + new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_pwrite")); + defineFunction(context, module, "fd_read", types(FD_TYPE, IOVEC_ARRAY_ADDRESS_TYPE, IOVEC_ARRAY_LENGTH_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), + new WasiFdReadNode(language, module)); + defineFunction(context, module, "fd_readdir", types(FD_TYPE, POINTER_TYPE, SIZE_TYPE, DIRCOOKIE_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), + new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_readdir")); + defineFunction(context, module, "fd_renumber", types(FD_TYPE, FD_TYPE), types(ERRNO_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_renumber")); + defineFunction(context, module, "fd_seek", types(FD_TYPE, FILEDELTA_TYPE, WHENCE_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), new WasiFdSeekNode(language, module)); + defineFunction(context, module, "fd_sync", types(FD_TYPE), types(ERRNO_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_sync")); + defineFunction(context, module, "fd_tell", types(FD_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_fd_tell")); + defineFunction(context, module, "fd_write", types(FD_TYPE, CIOVEC_ARRAY_ADDRESS_TYPE, CIOVEC_ARRAY_LENGTH_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), + new WasiFdWriteNode(language, module)); + defineFunction(context, module, "path_create_directory", types(FD_TYPE, STRING_ADDRESS_TYPE, STRING_LENGTH_TYPE), types(ERRNO_TYPE), new WasiPathCreateDirectoryNode(language, module)); + defineFunction(context, module, "path_filestat_get", types(FD_TYPE, LOOKUPFLAGS_TYPE, STRING_ADDRESS_TYPE, STRING_LENGTH_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), + new WasiPathFileStatGetNode(language, module)); + defineFunction(context, module, "path_filestat_set_times", types(FD_TYPE, LOOKUPFLAGS_TYPE, STRING_ADDRESS_TYPE, STRING_LENGTH_TYPE, TIMESTAMP_TYPE, TIMESTAMP_TYPE, FSTFLAGS_TYPE), + types(ERRNO_TYPE), new WasiPathFilestatSetTimesNode(language, module)); - defineFunction(context, module, "path_link", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiPathLinkNode(language, module)); - defineFunction(context, module, "path_open", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE, I64_TYPE, I64_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), + defineFunction(context, module, "path_link", types(FD_TYPE, LOOKUPFLAGS_TYPE, STRING_ADDRESS_TYPE, STRING_LENGTH_TYPE, FD_TYPE, STRING_ADDRESS_TYPE, STRING_LENGTH_TYPE), types(ERRNO_TYPE), + new WasiPathLinkNode(language, module)); + defineFunction(context, module, "path_open", + types(FD_TYPE, LOOKUPFLAGS_TYPE, STRING_ADDRESS_TYPE, STRING_LENGTH_TYPE, OFLAGS_TYPE, RIGHTS_TYPE, RIGHTS_TYPE, FDFLAGS_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), new WasiPathOpenNode(language, module)); - defineFunction(context, module, "path_readlink", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiPathReadLinkNode(language, module)); - defineFunction(context, module, "path_remove_directory", types(I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiPathRemoveDirectoryNode(language, module)); - defineFunction(context, module, "path_rename", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiPathRenameNode(language, module)); - defineFunction(context, module, "path_symlink", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiPathSymlinkNode(language, module)); - defineFunction(context, module, "path_unlink_file", types(I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiPathUnlinkFileNode(language, module)); - defineFunction(context, module, "poll_oneoff", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_poll_oneoff")); - defineFunction(context, module, "proc_exit", types(I32_TYPE), types(), new WasiProcExitNode(language, module)); - defineFunction(context, module, "proc_raise", types(I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_proc_raise")); - defineFunction(context, module, "sched_yield", types(), types(I32_TYPE), new WasiSchedYieldNode(language, module)); + defineFunction(context, module, "path_readlink", types(FD_TYPE, STRING_ADDRESS_TYPE, STRING_LENGTH_TYPE, POINTER_TYPE, SIZE_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), + new WasiPathReadLinkNode(language, module)); + defineFunction(context, module, "path_remove_directory", types(FD_TYPE, STRING_ADDRESS_TYPE, STRING_LENGTH_TYPE), types(ERRNO_TYPE), new WasiPathRemoveDirectoryNode(language, module)); + defineFunction(context, module, "path_rename", types(FD_TYPE, STRING_ADDRESS_TYPE, STRING_LENGTH_TYPE, FD_TYPE, STRING_ADDRESS_TYPE, STRING_LENGTH_TYPE), types(ERRNO_TYPE), + new WasiPathRenameNode(language, module)); + defineFunction(context, module, "path_symlink", types(STRING_ADDRESS_TYPE, STRING_LENGTH_TYPE, FD_TYPE, STRING_ADDRESS_TYPE, STRING_LENGTH_TYPE), types(ERRNO_TYPE), + new WasiPathSymlinkNode(language, module)); + defineFunction(context, module, "path_unlink_file", types(FD_TYPE, STRING_ADDRESS_TYPE, STRING_LENGTH_TYPE), types(ERRNO_TYPE), new WasiPathUnlinkFileNode(language, module)); + defineFunction(context, module, "poll_oneoff", types(CONST_POINTER_TYPE, POINTER_TYPE, SIZE_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), + new WasiUnsupportedFunctionNode(language, module, "__wasi_poll_oneoff")); + defineFunction(context, module, "proc_exit", types(EXITCODE_TYPE), types(), new WasiProcExitNode(language, module)); + defineFunction(context, module, "proc_raise", types(SIGNAL_TYPE), types(ERRNO_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_proc_raise")); + defineFunction(context, module, "sched_yield", types(), types(ERRNO_TYPE), new WasiSchedYieldNode(language, module)); if (context.getContextOptions().constantRandomGet()) { - defineFunction(context, module, "random_get", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiConstantRandomGetNode(language, module)); + defineFunction(context, module, "random_get", types(POINTER_TYPE, SIZE_TYPE), types(ERRNO_TYPE), new WasiConstantRandomGetNode(language, module)); } else { - defineFunction(context, module, "random_get", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiRandomGetNode(language, module)); + defineFunction(context, module, "random_get", types(POINTER_TYPE, SIZE_TYPE), types(ERRNO_TYPE), new WasiRandomGetNode(language, module)); } - defineFunction(context, module, "sock_accept", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_sock_accept")); - defineFunction(context, module, "sock_recv", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_sock_recv")); - defineFunction(context, module, "sock_send", types(I32_TYPE, I32_TYPE, I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_sock_send")); - defineFunction(context, module, "sock_shutdown", types(I32_TYPE, I32_TYPE), types(I32_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_sock_shutdown")); + defineFunction(context, module, "sock_accept", types(FD_TYPE, FDFLAGS_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), + new WasiUnsupportedFunctionNode(language, module, "__wasi_sock_accept")); + defineFunction(context, module, "sock_recv", types(FD_TYPE, IOVEC_ARRAY_ADDRESS_TYPE, IOVEC_ARRAY_LENGTH_TYPE, RIFLAGS_TYPE, RETURN_VALUE_ADDRESS_TYPE, RETURN_VALUE_ADDRESS_TYPE), + types(ERRNO_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_sock_recv")); + defineFunction(context, module, "sock_send", types(FD_TYPE, CIOVEC_ARRAY_ADDRESS_TYPE, CIOVEC_ARRAY_LENGTH_TYPE, SIFLAGS_TYPE, RETURN_VALUE_ADDRESS_TYPE), types(ERRNO_TYPE), + new WasiUnsupportedFunctionNode(language, module, "__wasi_sock_send")); + defineFunction(context, module, "sock_shutdown", types(FD_TYPE, SDFLAGS_TYPE), types(ERRNO_TYPE), new WasiUnsupportedFunctionNode(language, module, "__wasi_sock_shutdown")); return module; } - } diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiPathReadLinkNode.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiPathReadLinkNode.java index 19ddb1ff18df..47ec3b93c99b 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiPathReadLinkNode.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/WasiPathReadLinkNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -66,16 +66,17 @@ public Object executeWithContext(VirtualFrame frame, WasmContext context, WasmIn (int) WasmArguments.getArgument(args, 1), (int) WasmArguments.getArgument(args, 2), (int) WasmArguments.getArgument(args, 3), - (int) WasmArguments.getArgument(args, 4)); + (int) WasmArguments.getArgument(args, 4), + (int) WasmArguments.getArgument(args, 5)); } @TruffleBoundary - private int pathReadLink(WasmContext context, WasmMemory memory, int fd, int pathAddress, int pathLength, int buf, int bufLen) { + private int pathReadLink(WasmContext context, WasmMemory memory, int fd, int pathAddress, int pathLength, int buf, int bufLen, int sizeAddress) { final Fd handle = context.fdManager().get(fd); if (handle == null) { return Errno.Badf.ordinal(); } - return handle.pathReadLink(this, memory, pathAddress, pathLength, buf, bufLen); + return handle.pathReadLink(this, memory, pathAddress, pathLength, buf, bufLen, sizeAddress); } @Override diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/fd/DirectoryFd.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/fd/DirectoryFd.java index 50b58075b15a..4a6c1fb2c1fc 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/fd/DirectoryFd.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/fd/DirectoryFd.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -315,7 +315,7 @@ public Errno pathOpen(Node node, WasmMemory memory, int dirFlags, int pathAddres } @Override - public int pathReadLink(Node node, WasmMemory memory, int pathAddress, int pathLength, int buf, int bufLen) { + public int pathReadLink(Node node, WasmMemory memory, int pathAddress, int pathLength, int buf, int bufLen, int sizeAddress) { if (!isSet(fsRightsBase, Rights.PathReadlink)) { return Errno.Notcapable.ordinal(); } @@ -330,7 +330,9 @@ public int pathReadLink(Node node, WasmMemory memory, int pathAddress, int pathL return Errno.Noent.ordinal(); } final String content = virtualLink.getPath(); - return memory.writeString(node, content, buf, bufLen); + int bytesWritten = memory.writeString(node, content, buf, bufLen); + memory.store_i32(node, sizeAddress, bytesWritten); + return Errno.Success.ordinal(); } catch (NotLinkException e) { return Errno.Nolink.ordinal(); } catch (IOException | UnsupportedOperationException e) { diff --git a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/fd/Fd.java b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/fd/Fd.java index 2d95a8ae0b7e..7c0a5923e24f 100644 --- a/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/fd/Fd.java +++ b/wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/predefined/wasi/fd/Fd.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -44,6 +44,7 @@ import com.oracle.truffle.api.nodes.Node; import org.graalvm.wasm.exception.WasmException; import org.graalvm.wasm.memory.WasmMemory; +import org.graalvm.wasm.predefined.wasi.types.Advice; import org.graalvm.wasm.predefined.wasi.types.Errno; import org.graalvm.wasm.predefined.wasi.types.Fdflags; import org.graalvm.wasm.predefined.wasi.types.Filetype; @@ -257,6 +258,14 @@ public Errno seek(Node node, WasmMemory memory, long offset, Whence whence, int return Errno.Acces; } + @SuppressWarnings("unused") + public Errno advise(long offset, long length, Advice advice) { + if (!isSet(fsRightsBase, Rights.FdAdvise)) { + return Errno.Notcapable; + } + return Errno.Success; + } + /** * Implementation of WASI fd_fdstat_get: @@ -480,11 +489,13 @@ public Errno pathLink(Node node, WasmMemory memory, int oldFlags, int oldPathAdd * @param pathLength length of the path to get, in bytes, including the trailing null character * @param buf the buffer to which to write the contents of the symbolic link * @param bufLen the length of the buffer + * @param sizeAddress {@code size*}: address at which to write the number of bytes written to + * {@code buf} * @return {@link Errno#Success} in case of success, or another {@link Errno} in case of error * @throws WasmException if an error happens while writing or reading to {@code memory} * @see Pre-opened directories */ - public int pathReadLink(Node node, WasmMemory memory, int pathAddress, int pathLength, int buf, int bufLen) { + public int pathReadLink(Node node, WasmMemory memory, int pathAddress, int pathLength, int buf, int bufLen, int sizeAddress) { if (!isSet(fsRightsBase, Rights.PathReadlink)) { return Errno.Notcapable.ordinal(); }