diff --git a/build/wasi.cmake b/build/wasi.cmake index 59be8c760..504d75808 100644 --- a/build/wasi.cmake +++ b/build/wasi.cmake @@ -7,20 +7,20 @@ if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU") list(APPEND uvwasi_cflags -fvisibility=hidden --std=gnu89) list(APPEND uvwasi_cflags -Wall -Wsign-compare -Wextra -Wstrict-prototypes) list(APPEND uvwasi_cflags -Wno-unused-parameter) -endif() - -set( CMAKE_C_FLAGS -fPIC) + set( CMAKE_C_FLAGS -fPIC) -if(DEFINED WALRUS_ARCH) - if(${WALRUS_ARCH} STREQUAL "x86") + if(DEFINED WALRUS_ARCH) + if(${WALRUS_ARCH} STREQUAL "x86") set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") + endif() endif() -endif() -if(DEFINED WALRUS_MODE) - if(${WALRUS_MODE} STREQUAL "debug") - set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") + if(DEFINED WALRUS_MODE) + if(${WALRUS_MODE} STREQUAL "debug") + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") + endif() endif() + endif() if(APPLE) diff --git a/src/shell/Shell.cpp b/src/shell/Shell.cpp index 09b3fb50a..997ec0ced 100644 --- a/src/shell/Shell.cpp +++ b/src/shell/Shell.cpp @@ -290,7 +290,31 @@ static Trap::TrapResult executeWASM(Store* store, const std::string& filename, c Walrus::Trap trap; return trap.run([](ExecutionState& state, void* d) { RunData* data = reinterpret_cast(d); - data->module->instantiate(state, data->importValues); + Instance* instance = data->module->instantiate(state, data->importValues); + + for (auto&& exp : data->module->exports()) { + if (exp->exportType() == ExportType::Function) { + if ("_start" != exp->name()) { + continue; + } + + auto fn = instance->function(exp->itemIndex()); + FunctionType* fnType = fn->asDefinedFunction()->moduleFunction()->functionType(); + + if (!fnType->param().empty()) { + printf("warning: function %s has params, but params are not supported\n", exp->name().c_str()); + return; + } + + if (!fnType->result().empty()) { + printf("warning: function %s has results, but results are not supported\n", exp->name().c_str()); + return; + } + + + fn->call(state, nullptr, nullptr); + } + } }, &data); } @@ -872,7 +896,7 @@ static void executeWAST(Store* store, const std::string& filename, const std::ve } } -static void runExports(Store* store, const std::string& filename, const std::vector& src, std::string& exportToRun) +static void runExports(Store* store, const std::string& filename, const std::vector& src, std::string& exportToRun, SpecTestFunctionTypes& functionTypes) { auto parseResult = WASMParser::parseBinary(store, filename, src.data(), src.size()); @@ -888,21 +912,38 @@ static void runExports(Store* store, const std::string& filename, const std::vec } const auto& importTypes = module->imports(); + ExternVector importValues; + importValues.reserve(importTypes.size()); - if (importTypes.size() != 0) { - fprintf(stderr, "error: module has imports, but imports are not supported\n"); - return; + for (size_t i = 0; i < importTypes.size(); i++) { + auto import = importTypes[i]; + if (import->moduleName() == "wasi_snapshot_preview1") { + Walrus::WASI::WasiFunc* wasiImportFunc = WASI::find(import->fieldName()); + if (wasiImportFunc != nullptr) { + FunctionType* fn = functionTypes[wasiImportFunc->functionType]; + if (fn->equals(import->functionType())) { + importValues.push_back(WasiFunction::createWasiFunction( + store, + const_cast(import->functionType()), + wasiImportFunc->ptr)); + } + } + } else { + fprintf(stderr, "error: module has imports, but imports are not supported\n"); + return; + } } struct RunData { Module* module; + ExternVector& importValues; std::string* exportToRun; - } data = { module.value(), &exportToRun }; + } data = { module.value(), importValues, &exportToRun }; Walrus::Trap trap; trap.run([](ExecutionState& state, void* d) { auto data = reinterpret_cast(d); - Instance* instance = data->module->instantiate(state, ExternVector()); + Instance* instance = data->module->instantiate(state, data->importValues); for (auto&& exp : data->module->exports()) { if (exp->exportType() == ExportType::Function) { @@ -1033,7 +1074,7 @@ int main(int argc, char* argv[]) } if (endsWith(filePath, "wasm")) { if (!argParser.exportToRun.empty()) { - runExports(store, filePath, buf, argParser.exportToRun); + runExports(store, filePath, buf, argParser.exportToRun, functionTypes); } else { auto trapResult = executeWASM(store, filePath, buf, functionTypes); if (trapResult.exception) { @@ -1051,9 +1092,9 @@ int main(int argc, char* argv[]) } // finalize + delete wasi; delete store; delete engine; - delete wasi; #if defined(WALRUS_GOOGLE_PERF) ProfilerStop(); diff --git a/src/wasi/Fd.h b/src/wasi/Fd.h index e27676868..8c86a3df8 100644 --- a/src/wasi/Fd.h +++ b/src/wasi/Fd.h @@ -22,7 +22,6 @@ void WASI::fd_write(ExecutionState& state, Value* argv, Value* result, Instance* uint32_t iovptr = argv[1].asI32(); uint32_t iovcnt = argv[2].asI32(); uint32_t out = argv[3].asI32(); - WASI::wasi_iovec_t wasi_iovs; if (!WASI::checkMemOffset(instance->memory(0), iovptr, iovcnt)) { result[0] = Value(static_cast(WASI::wasi_errno::inval)); @@ -30,17 +29,14 @@ void WASI::fd_write(ExecutionState& state, Value* argv, Value* result, Instance* return; } - uint32_t offset = *reinterpret_cast(instance->memory(0)->buffer() + iovptr); - wasi_iovs.buf = reinterpret_cast(instance->memory(0)->buffer() + offset); - wasi_iovs.len = *reinterpret_cast(instance->memory(0)->buffer() + iovptr + sizeof(uvwasi_size_t)); - std::vector iovs(iovcnt); for (uint32_t i = 0; i < iovcnt; i++) { - iovs[i].buf_len = wasi_iovs.len; - iovs[0].buf = wasi_iovs.buf; + iovs[i].buf = instance->memory(0)->buffer() + *reinterpret_cast(instance->memory(0)->buffer() + iovptr + i * 8); + iovs[i].buf_len = *(instance->memory(0)->buffer() + iovptr + 4 + i * 8); } - uvwasi_size_t out_addr; + uvwasi_size_t out_addr = *(instance->memory(0)->buffer() + out); + result[0] = Value(static_cast(uvwasi_fd_write(WASI::m_uvwasi, fd, iovs.data(), iovs.size(), &out_addr))); *(instance->memory(0)->buffer() + out) = out_addr; } diff --git a/src/wasi/Wasi.h b/src/wasi/Wasi.h index f7d7be360..c90d976ee 100644 --- a/src/wasi/Wasi.h +++ b/src/wasi/Wasi.h @@ -114,12 +114,6 @@ class WASI { ERRORS(TO_ENUM) } wasi_errno_t; #undef TO_ENUM - - typedef struct wasi_iovec { - uint8_t* buf; - uint32_t len; - } wasi_iovec_t; - // end of type definitions WASI(); diff --git a/test/wasi/hello_world.wast b/test/wasi/hello_world.wast deleted file mode 100644 index 49367b31d..000000000 --- a/test/wasi/hello_world.wast +++ /dev/null @@ -1,24 +0,0 @@ -(module - (import "wasi_snapshot_preview1" "fd_write" (func $__wasi_fd_write (param i32 i32 i32 i32) (result i32))) - (memory 1) - - (export "memory" (memory 0)) - (export "_start" (func $_start)) - (data (i32.const 0) "Hello World!\n") - - (func $_start (result i32) - (i32.store (i32.const 24) (i32.const 13)) ;; Lenght of "Hello World!\n" - (i32.store (i32.const 20) (i32.const 0)) ;; memory offset of "Hello World!\n" - (call $__wasi_fd_write - (i32.const 1) ;;file descriptor - (i32.const 20) ;;offset of str offset - (i32.const 1) ;;iovec length - (i32.const 30) ;;result offset - ) - drop - i32.const 32 - i32.load - ) -) - -(assert_return (invoke "_start") (i32.const 0)) diff --git a/test/wasi/hello_world/hello_world.c b/test/wasi/hello_world/hello_world.c new file mode 100644 index 000000000..c8c046b01 --- /dev/null +++ b/test/wasi/hello_world/hello_world.c @@ -0,0 +1,14 @@ +#include +#include + +/* Emscripten compile command: +`emcc hello_world.c --no-entry -sEXPORTED_FUNCTIONS=_start -s EXPORTED_RUNTIME_METHODS=ccall,cwrap -o hello_world.wasm` + + Run in walrus with `walrus --run-export _start hello_world.wasm` +*/ + +int main() +{ + fprintf(stdout, "Hello World!\n"); + return 0; +} diff --git a/test/wasi/hello_world/hello_world.wasm b/test/wasi/hello_world/hello_world.wasm new file mode 100755 index 000000000..4f582cb49 Binary files /dev/null and b/test/wasi/hello_world/hello_world.wasm differ diff --git a/test/wasi/hello_world/hello_world.wast b/test/wasi/hello_world/hello_world.wast new file mode 100644 index 000000000..0d486f4b5 --- /dev/null +++ b/test/wasi/hello_world/hello_world.wast @@ -0,0 +1,23 @@ +(module + (import "wasi_snapshot_preview1" "fd_write" (func $wasi_fd_write (param i32 i32 i32 i32) (result i32))) + (memory 1) + + (export "memory" (memory 0)) + (export "hello_world" (func $hello_world)) + (data (i32.const 0) "Hello World!\n") + + (func $hello_world + (i32.store (i32.const 100) (i32.const 0)) + (i32.store (i32.const 112) (i32.const 13)) + (i32.store (i32.const 200) (i32.const 0)) + (call $wasi_fd_write + (i32.const 1) ;;file descriptor + (i32.const 100) ;;offset of str offset + (i32.const 2) ;;iovec length + (i32.const 200) ;;result offset + ) + drop + ) +) + +(assert_return (invoke "hello_world")) diff --git a/test/wasi/proc_exit.wast b/test/wasi/proc_exit.wast deleted file mode 100644 index 0fbdc1081..000000000 --- a/test/wasi/proc_exit.wast +++ /dev/null @@ -1,11 +0,0 @@ -(module - (import "wasi_snapshot_preview1" "proc_exit" (func $exit (param i32))) - - - (func (export "start") - i32.const 0 - call $exit - ) -) - -(assert_return (invoke "start")) diff --git a/test/wasi/proc_exit/proc_exit.c b/test/wasi/proc_exit/proc_exit.c new file mode 100644 index 000000000..7f57d6cdd --- /dev/null +++ b/test/wasi/proc_exit/proc_exit.c @@ -0,0 +1,7 @@ +#include "stdlib.h" + +int main() +{ + exit(0); + return 0; +} \ No newline at end of file diff --git a/test/wasi/proc_exit/proc_exit.wasm b/test/wasi/proc_exit/proc_exit.wasm new file mode 100755 index 000000000..7122b0f00 Binary files /dev/null and b/test/wasi/proc_exit/proc_exit.wasm differ diff --git a/test/wasi/proc_exit/proc_exit.wast b/test/wasi/proc_exit/proc_exit.wast new file mode 100644 index 000000000..e0878b962 --- /dev/null +++ b/test/wasi/proc_exit/proc_exit.wast @@ -0,0 +1,11 @@ +(module + (import "wasi_snapshot_preview1" "proc_exit" (func $wasi_proc_exit (param i32))) + + + (func (export "proc_exit") + i32.const 0 + call $wasi_proc_exit + ) +) + +(assert_return (invoke "proc_exit"))