From 3d5569f0dd9bb6374c33531e217b2b2a937a2178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20L=C3=A1szl=C3=B3=20Kulcs=C3=A1r?= Date: Tue, 10 Dec 2024 13:28:25 +0100 Subject: [PATCH] Implement file related function and simplify function declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement fd_prestat_get, fd_prestat_dir_name and add tests for them. Also simplify function declarations with a marco. Signed-off-by: Ádám László Kulcsár --- src/runtime/DefinedFunctionTypes.h | 23 ++++++++++++++ src/wasi/WASI.cpp | 27 ++++++++++++++++ src/wasi/WASI.h | 21 ++++--------- test/wasi/fd_advise.wast | 50 ++++++++++++++++++++++++++++++ test/wasi/fd_prestat.wast | 28 +++++++++++++++++ 5 files changed, 134 insertions(+), 15 deletions(-) create mode 100644 test/wasi/fd_advise.wast create mode 100644 test/wasi/fd_prestat.wast diff --git a/src/runtime/DefinedFunctionTypes.h b/src/runtime/DefinedFunctionTypes.h index fb0c002ba..f70cb3cf6 100644 --- a/src/runtime/DefinedFunctionTypes.h +++ b/src/runtime/DefinedFunctionTypes.h @@ -32,8 +32,10 @@ class DefinedFunctionTypes { I32_RI32, I32I32_RI32, I32I64I32_RI32, + I32I32I32_RI32, I32I32I32I32_RI32, I32I64I32I32_RI32, + I32I64I64I32_RI32, I32I32I32I32I32I64I64I32I32_RI32, RI32, I64R, @@ -93,6 +95,16 @@ class DefinedFunctionTypes { result->push_back(Value::Type::I32); m_vector[index++] = new FunctionType(param, result); } + { + // I32I32I32_RI32 + param = new ValueTypeVector(); + result = new ValueTypeVector(); + param->push_back(Value::Type::I32); + param->push_back(Value::Type::I32); + param->push_back(Value::Type::I32); + result->push_back(Value::Type::I32); + m_vector[index++] = new FunctionType(param, result); + } { // I32I32I32I32_RI32 param = new ValueTypeVector(); @@ -115,6 +127,17 @@ class DefinedFunctionTypes { result->push_back(Value::Type::I32); m_vector[index++] = new FunctionType(param, result); } + { + // I32I64I64I32_RI32 + param = new ValueTypeVector(); + result = new ValueTypeVector(); + param->push_back(Value::Type::I32); + param->push_back(Value::Type::I64); + param->push_back(Value::Type::I64); + param->push_back(Value::Type::I32); + result->push_back(Value::Type::I32); + m_vector[index++] = new FunctionType(param, result); + } { // I32I32I32I32I32I64I64I32I32_RI32 param = new ValueTypeVector(); diff --git a/src/wasi/WASI.cpp b/src/wasi/WASI.cpp index 7c04d543b..1dbb04d2a 100644 --- a/src/wasi/WASI.cpp +++ b/src/wasi/WASI.cpp @@ -243,6 +243,23 @@ void WASI::fd_fdstat_get(ExecutionState& state, Value* argv, Value* result, Inst result[0] = Value(uvwasi_fd_fdstat_get(WASI::g_uvwasi, fd, fdstat)); } +void WASI::fd_prestat_get(ExecutionState& state, Value* argv, Value* result, Instance* instance) +{ + uint32_t fd = argv[0].asI32(); + uvwasi_prestat_t* buf = reinterpret_cast(get_memory_pointer(instance, argv[1], sizeof(uvwasi_prestat_t))); + + result[0] = Value(uvwasi_fd_prestat_get(WASI::g_uvwasi, fd, buf)); +} + +void WASI::fd_prestat_dir_name(ExecutionState& state, Value* argv, Value* result, Instance* instance) +{ + uint32_t fd = argv[0].asI32(); + uint32_t length = argv[2].asI32(); + char* path = reinterpret_cast(get_memory_pointer(instance, argv[1], length)); + + result[0] = Value(uvwasi_fd_prestat_dir_name(WASI::g_uvwasi, fd, path, length)); +} + void WASI::fd_seek(ExecutionState& state, Value* argv, Value* result, Instance* instance) { uint32_t fd = argv[0].asI32(); @@ -253,6 +270,16 @@ void WASI::fd_seek(ExecutionState& state, Value* argv, Value* result, Instance* result[0] = Value(uvwasi_fd_seek(WASI::g_uvwasi, fd, fileDelta, whence, file_size)); } +void WASI::fd_advise(ExecutionState& state, Value* argv, Value* result, Instance* instance) +{ + uint32_t fd = argv[0].asI32(); + uint64_t offset = argv[1].asI64(); + uint64_t len = argv[2].asI64(); + uint32_t advise = argv[3].asI32(); + + result[0] = Value(uvwasi_fd_advise(WASI::g_uvwasi, fd, offset, len, advise)); +} + void WASI::path_open(ExecutionState& state, Value* argv, Value* result, Instance* instance) { uint32_t fd = argv[0].asI32(); diff --git a/src/wasi/WASI.h b/src/wasi/WASI.h index cca3980fa..cdb96c5f0 100644 --- a/src/wasi/WASI.h +++ b/src/wasi/WASI.h @@ -47,7 +47,10 @@ class WASI { F(fd_read, I32I32I32I32_RI32) \ F(fd_close, I32_RI32) \ F(fd_fdstat_get, I32I32_RI32) \ + F(fd_prestat_dir_name, I32I32I32_RI32) \ + F(fd_prestat_get, I32I32_RI32) \ F(fd_seek, I32I64I32I32_RI32) \ + F(fd_advise, I32I64I64I32_RI32) \ F(path_open, I32I32I32I32I32I64I64I32I32_RI32) \ F(environ_get, I32I32_RI32) \ F(environ_sizes_get, I32I32_RI32) @@ -155,21 +158,9 @@ class WASI { private: // wasi functions - static void args_get(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void args_sizes_get(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void proc_exit(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void proc_raise(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void clock_res_get(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void clock_time_get(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void fd_write(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void fd_read(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void fd_close(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void fd_fdstat_get(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void fd_seek(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void path_open(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void environ_get(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void environ_sizes_get(ExecutionState& state, Value* argv, Value* result, Instance* instance); - static void random_get(ExecutionState& state, Value* argv, Value* result, Instance* instance); +#define DECLARE_FUNCTION(NAME, FUNCTYPE) static void NAME(ExecutionState& state, Value* argv, Value* result, Instance* instance); + FOR_EACH_WASI_FUNC(DECLARE_FUNCTION) +#undef DECLARE_FUNCTION static uvwasi_t* g_uvwasi; static WasiFuncInfo g_wasiFunctions[FuncEnd]; diff --git a/test/wasi/fd_advise.wast b/test/wasi/fd_advise.wast new file mode 100644 index 000000000..3f87251de --- /dev/null +++ b/test/wasi/fd_advise.wast @@ -0,0 +1,50 @@ +(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))) + + (memory $mem 1) + (data (i32.const 300) "./write_to_this.txt") ;; Filename in current directory (where Walrus is ran from) + + (func (export "test_advise") (param i32) (result i32) ;; advice is passed as param, return is if the function returned succesfully + i32.const 3 ;; Directory file descriptior, by default 3 is the first opened directory + i32.const 1 ;; lookupflags: directory + i32.const 300 ;; Offset of file name in memory + i32.const 19 ;; Length of file name + i32.const 0 ;; oflags: none + i64.const 128 ;; rights: fd_advise + i64.const 128 ;; rights_inheriting: fd_advise + i32.const 0 ;; fdflags: none + i32.const 0 ;; Offset to store at the opened file descriptor in memory + call $path_open + + i32.eqz ;; fail if file could not be opened + (if + (then) + (else + i32.const 1 + return + ) + ) + + + i32.const 0 + i32.load ;; Get the file descriptor + i64.const 0 ;; Start for 0 offset + i64.const 0 ;; For the entire file + local.get 0 ;; Advise + call $fd_advise + return + ) + + (export "memory" (memory 0)) +) + +(assert_return (invoke "test_advise" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "test_advise" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "test_advise" (i32.const 2)) (i32.const 0)) +(assert_return (invoke "test_advise" (i32.const 3)) (i32.const 0)) +(assert_return (invoke "test_advise" (i32.const 4)) (i32.const 0)) +(assert_return (invoke "test_advise" (i32.const 5)) (i32.const 0)) + +(assert_return (invoke "test_advise" (i32.const 6)) (i32.const 28)) ;; Returns invalid function argument, as it should + diff --git a/test/wasi/fd_prestat.wast b/test/wasi/fd_prestat.wast new file mode 100644 index 000000000..a66621382 --- /dev/null +++ b/test/wasi/fd_prestat.wast @@ -0,0 +1,28 @@ +(module + (import "wasi_snapshot_preview1" "fd_prestat_get" (func $fd_prestat_get (param i32 i32) (result i32))) + (import "wasi_snapshot_preview1" "fd_prestat_dir_name" (func $fd_prestat_dir_name (param i32 i32 i32) (result i32))) + (memory $mem 1) + + (; fd_prestat_get return information about a preopened file, + meaning one that was passed with '--mapdirs' ;) + + (func (export "test_prestat_get") (param i32) (result i32) + local.get 0 ;; file descriptor + i32.const 0 ;; stored information offset in memory + call $fd_prestat_get + ) + + (func (export "test_prestat_dir_name") (param i32) (result i32) + local.get 0 ;; file descriptor + i32.const 0 ;; stored information offset in memory + i32.const 128 ;; max lenght of file path + call $fd_prestat_dir_name + ) +) + +(assert_return (invoke "test_prestat_get" (i32.const 3)) (i32.const 0)) +(assert_return (invoke "test_prestat_get" (i32.const 4)) (i32.const 8)) ;; Error 8: bad file descriptor because it does not exist +(assert_return (invoke "test_prestat_dir_name" (i32.const 3)) (i32.const 0)) ;; mapped directory +(assert_return (invoke "test_prestat_dir_name" (i32.const 0)) (i32.const 8)) ;; Error 8: bad file descriptor because stdin is not a mapped directory +(assert_return (invoke "test_prestat_dir_name" (i32.const 4)) (i32.const 8)) ;; Error 8: bad file descriptor because it does not exist +