diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 0b940599a..0b7d31163 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -133,7 +133,7 @@ jobs: install: | apt-get update - apt-get install -y cmake build-essential ninja-build pkg-config python3 clang-12 + apt-get install -y cmake build-essential ninja-build pkg-config python3 clang-12 git #FIXME fix clang version as to 12 ln -s /usr/bin/clang-12 /usr/bin/clang ln -s /usr/bin/clang++-12 /usr/bin/clang++ @@ -164,7 +164,7 @@ jobs: install: | apt-get update - apt-get install -y cmake build-essential ninja-build pkg-config python3 clang-12 + apt-get install -y cmake build-essential ninja-build pkg-config python3 clang-12 git #FIXME fix clang version as to 12 ln -s /usr/bin/clang-12 /usr/bin/clang ln -s /usr/bin/clang++-12 /usr/bin/clang++ diff --git a/.gitmodules b/.gitmodules index 222c2e3c2..eea548038 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,3 +6,6 @@ path = third_party/wasm-c-api url = https://github.com/WebAssembly/wasm-c-api ignore = untracked +[submodule "third_party/uvwasi"] + path = third_party/uvwasi + url = https://github.com/nodejs/uvwasi.git diff --git a/CMakeLists.txt b/CMakeLists.txt index d60946949..8c9f22373 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,4 +74,5 @@ PROCESSORCOUNT (NPROCS) # INCLUDE CMAKE FILES INCLUDE (${PROJECT_SOURCE_DIR}/build/config.cmake) +INCLUDE (${PROJECT_SOURCE_DIR}/build/wasi.cmake) INCLUDE (${PROJECT_SOURCE_DIR}/build/walrus.cmake) diff --git a/build/walrus.cmake b/build/walrus.cmake index 07de650a9..cec929e24 100644 --- a/build/walrus.cmake +++ b/build/walrus.cmake @@ -65,7 +65,12 @@ ENDIF() SET (WABT_DEFINITIONS ${WALRUS_DEFINITIONS}) SET (WITH_EXCEPTIONS TRUE) ADD_SUBDIRECTORY (third_party/wabt) -SET (WALRUS_LIBRARIES ${WALRUS_LIBRARIES} wabt) + +# uvwasi +INCLUDE_DIRECTORIES (${WALRUS_INCDIRS} PRIVATE ${WALRUS_THIRD_PARTY_ROOT}/uvwasi/include) +INCLUDE_DIRECTORIES (${WALRUS_INCDIRS} PRIVATE ${CMAKE_BINARY_DIR}/_deps/libuv-src/include) + +SET (WALRUS_LIBRARIES ${WALRUS_LIBRARIES} wabt uvwasi_a) # BUILD INCLUDE_DIRECTORIES (${WALRUS_INCDIRS}) diff --git a/build/wasi.cmake b/build/wasi.cmake new file mode 100644 index 000000000..59be8c760 --- /dev/null +++ b/build/wasi.cmake @@ -0,0 +1,86 @@ +# This can be a commit hash or tag +set(LIBUV_VERSION v1.44.2) + +include(CMakeDependentOption) + +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) + +if(DEFINED WALRUS_ARCH) + if(${WALRUS_ARCH} STREQUAL "x86") + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") + endif() +endif() + +if(DEFINED WALRUS_MODE) + if(${WALRUS_MODE} STREQUAL "debug") + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") + endif() +endif() + +if(APPLE) + set(CMAKE_MACOSX_RPATH ON) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + list(APPEND uvwasi_defines _GNU_SOURCE _POSIX_C_SOURCE=200112) +endif() + +set(CMAKE_MESSAGE_LOG_LEVEL "WARNING") + +include(FetchContent) +## https://libuv.org +FetchContent_Declare( + libuv + GIT_REPOSITORY https://github.com/libuv/libuv.git + GIT_TAG ${LIBUV_VERSION}) +FetchContent_GetProperties(libuv) +if(NOT libuv_POPULATED) + FetchContent_Populate(libuv) + include_directories("${libuv_SOURCE_DIR}/include") + add_subdirectory(${libuv_SOURCE_DIR} ${libuv_BINARY_DIR} EXCLUDE_FROM_ALL) +endif() +set(LIBUV_INCLUDE_DIR ${libuv_SOURCE_DIR}/include) +set(LIBUV_LIBRARIES uv_a) + +## uvwasi source code files. +set(uvwasi_sources + third_party/uvwasi/src/clocks.c + third_party/uvwasi/src/fd_table.c + third_party/uvwasi/src/path_resolver.c + third_party/uvwasi/src/poll_oneoff.c + third_party/uvwasi/src/sync_helpers.c + third_party/uvwasi/src/uv_mapping.c + third_party/uvwasi/src/uvwasi.c + third_party/uvwasi/src/wasi_rights.c + third_party/uvwasi/src/wasi_serdes.c +) + +option(UVWASI_DEBUG_LOG "Enable debug logging" OFF) +if(UVWASI_DEBUG_LOG) + list(APPEND uvwasi_cflags -DUVWASI_DEBUG_LOG) +endif() + +## Static library target. +add_library(uvwasi_a STATIC ${uvwasi_sources}) +target_compile_definitions(uvwasi_a PRIVATE ${uvwasi_defines}) +target_compile_options(uvwasi_a PRIVATE ${uvwasi_cflags}) +target_include_directories(uvwasi_a PRIVATE ${PROJECT_SOURCE_DIR}/include) +target_link_libraries(uvwasi_a PRIVATE ${LIBUV_LIBRARIES}) + +set(CMAKE_MESSAGE_LOG_LEVEL "DEFAULT") + +message(STATUS "summary of uvwasi build options: + Compiler: + C compiler: ${CMAKE_C_COMPILER} + CFLAGS: ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS} + + LibUV libraries: ${LIBUV_LIBRARIES} + LibUV includes: ${LIBUV_INCLUDE_DIR} + Debug logging: ${UVWASI_DEBUG_LOG} +") diff --git a/src/runtime/Function.cpp b/src/runtime/Function.cpp index a225f7565..b57c7fe96 100644 --- a/src/runtime/Function.cpp +++ b/src/runtime/Function.cpp @@ -149,4 +149,47 @@ void ImportedFunction::call(ExecutionState& state, Value* argv, Value* result) m_callback(newState, argv, result, m_data); } +WasiFunction* WasiFunction::createWasiFunction(Store* store, + FunctionType* functionType, + WasiFunctionCallback callback) +{ + WasiFunction* func = new WasiFunction(functionType, + callback); + store->appendExtern(func); + return func; +} + +void WasiFunction::interpreterCall(ExecutionState& state, uint8_t* bp, ByteCodeStackOffset* offsets, + uint16_t parameterOffsetCount, uint16_t resultOffsetCount) +{ + const FunctionType* ft = functionType(); + const ValueTypeVector& paramTypeInfo = ft->param(); + const ValueTypeVector& resultTypeInfo = ft->result(); + + ALLOCA(Value, paramVector, sizeof(Value) * paramTypeInfo.size()); + ALLOCA(Value, resultVector, sizeof(Value) * resultTypeInfo.size()); + + size_t offsetIndex = 0; + size_t size = paramTypeInfo.size(); + Value* paramVectorStart = paramVector; + for (size_t i = 0; i < size; i++) { + paramVector[i] = Value(paramTypeInfo[i], bp + offsets[offsetIndex]); + offsetIndex += valueFunctionCopyCount(paramTypeInfo[i]); + } + + call(state, paramVectorStart, resultVector); + + for (size_t i = 0; i < resultTypeInfo.size(); i++) { + resultVector[i].writeToMemory(bp + offsets[offsetIndex]); + offsetIndex += valueFunctionCopyCount(resultTypeInfo[i]); + } +} + +void WasiFunction::call(ExecutionState& state, Value* argv, Value* result) +{ + ExecutionState newState(state, this); + CHECK_STACK_LIMIT(newState); + m_callback(newState, argv, result, this->m_runningInstance); +} + } // namespace Walrus diff --git a/src/runtime/Function.h b/src/runtime/Function.h index c4d8ab4ed..6b0c9905c 100644 --- a/src/runtime/Function.h +++ b/src/runtime/Function.h @@ -43,6 +43,7 @@ class FunctionType; class ModuleFunction; class DefinedFunction; class ImportedFunction; +class WasiFunction; class Function : public Extern { public: @@ -72,6 +73,11 @@ class Function : public Extern { return false; } + virtual bool isWasiFunction() const + { + return false; + } + DefinedFunction* asDefinedFunction() { ASSERT(isDefinedFunction()); @@ -84,6 +90,12 @@ class Function : public Extern { return reinterpret_cast(this); } + WasiFunction* asWasiFunction() + { + ASSERT(isWasiFunction()); + return reinterpret_cast(this); + } + protected: Function(FunctionType* functionType) : m_functionType(functionType) @@ -168,6 +180,41 @@ class ImportedFunction : public Function { void* m_data; }; +class WasiFunction : public Function { +public: + typedef std::function WasiFunctionCallback; + + static WasiFunction* createWasiFunction(Store* store, + FunctionType* functionType, + WasiFunctionCallback callback); + + virtual bool isWasiFunction() const override + { + return true; + } + + void setRunningInstance(Instance* instance) + { + m_runningInstance = instance; + } + + virtual void call(ExecutionState& state, Value* argv, Value* result) override; + virtual void interpreterCall(ExecutionState& state, uint8_t* bp, ByteCodeStackOffset* offsets, + uint16_t parameterOffsetCount, uint16_t resultOffsetCount) override; + +protected: + WasiFunction(FunctionType* functionType, + WasiFunctionCallback callback) + : Function(functionType) + , m_callback(callback) + , m_runningInstance(nullptr) + { + } + + WasiFunctionCallback m_callback; + Instance* m_runningInstance; +}; + } // namespace Walrus #endif // __WalrusFunction__ diff --git a/src/runtime/Module.cpp b/src/runtime/Module.cpp index 430f0eea3..c52e4d6fc 100644 --- a/src/runtime/Module.cpp +++ b/src/runtime/Module.cpp @@ -28,6 +28,7 @@ #include "interpreter/ByteCode.h" #include "interpreter/Interpreter.h" #include "parser/WASMParser.h" +#include "wasi/Wasi.h" namespace Walrus { @@ -151,7 +152,11 @@ Instance* Module::instantiate(ExecutionState& state, const ExternVector& imports if (!imports[i]->asFunction()->functionType()->equals(m_imports[i]->functionType())) { Trap::throwException(state, "imported function type mismatch"); } - instance->m_functions[funcIndex++] = imports[i]->asFunction(); + instance->m_functions[funcIndex] = imports[i]->asFunction(); + if (imports[i]->asFunction()->isWasiFunction()) { + instance->m_functions[funcIndex]->asWasiFunction()->setRunningInstance(instance); + } + funcIndex++; break; } case ImportType::Global: { diff --git a/src/runtime/SpecTest.h b/src/runtime/SpecTest.h index 65062014d..94193a401 100644 --- a/src/runtime/SpecTest.h +++ b/src/runtime/SpecTest.h @@ -26,6 +26,8 @@ class SpecTestFunctionTypes { // The R is meant to represent the results, after R are the result types. NONE = 0, I32R, + I32_RI32, + I32I32I32I32_RI32, RI32, I64R, F32R, @@ -57,6 +59,25 @@ class SpecTestFunctionTypes { param->push_back(Value::Type::I32); m_vector[index++] = new FunctionType(param, result); } + { + // I32_RI32 + param = new ValueTypeVector(); + result = new ValueTypeVector(); + param->push_back(Value::Type::I32); + result->push_back(Value::Type::I32); + m_vector[index++] = new FunctionType(param, result); + } + { + // I32I32I32I32_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); + param->push_back(Value::Type::I32); + result->push_back(Value::Type::I32); + m_vector[index++] = new FunctionType(param, result); + } { // RI32 param = new ValueTypeVector(); diff --git a/src/shell/Shell.cpp b/src/shell/Shell.cpp index 69f073976..09b3fb50a 100644 --- a/src/shell/Shell.cpp +++ b/src/shell/Shell.cpp @@ -110,7 +110,7 @@ static void printF64(double v) printf("%s : f64\n", formatDecmialString(ss.str()).c_str()); } -static Trap::TrapResult executeWASM(Store* store, const std::string& filename, const std::vector& src, SpecTestFunctionTypes& functionTypes, WASI* wasi, +static Trap::TrapResult executeWASM(Store* store, const std::string& filename, const std::vector& src, SpecTestFunctionTypes& functionTypes, std::map* registeredInstanceMap = nullptr) { auto parseResult = WASMParser::parseBinary(store, filename, src.data(), src.size()); @@ -239,15 +239,14 @@ static Trap::TrapResult executeWASM(Store* store, const std::string& filename, c nullptr)); } } else if (import->moduleName() == "wasi_snapshot_preview1") { - Walrus::WASI::WasiFunc* wasiImportFunc = wasi->find(import->fieldName()); + Walrus::WASI::WasiFunc* wasiImportFunc = WASI::find(import->fieldName()); if (wasiImportFunc != nullptr) { FunctionType* fn = functionTypes[wasiImportFunc->functionType]; if (fn->equals(import->functionType())) { - importValues.push_back(ImportedFunction::createImportedFunction( + importValues.push_back(WasiFunction::createWasiFunction( store, const_cast(import->functionType()), - wasiImportFunc->ptr, - nullptr)); + wasiImportFunc->ptr)); } } } else if (registeredInstanceMap) { @@ -647,7 +646,7 @@ static Instance* fetchInstance(wabt::Var& moduleVar, std::map return registeredInstanceMap[moduleVar.name()]; } -static void executeWAST(Store* store, const std::string& filename, const std::vector& src, SpecTestFunctionTypes& functionTypes, WASI* wasi) +static void executeWAST(Store* store, const std::string& filename, const std::vector& src, SpecTestFunctionTypes& functionTypes) { auto lexer = wabt::WastLexer::CreateBufferLexer("test.wabt", src.data(), src.size()); if (lexer == nullptr) { @@ -679,7 +678,7 @@ static void executeWAST(Store* store, const std::string& filename, const std::ve case wabt::CommandType::ScriptModule: { auto* moduleCommand = static_cast(command.get()); auto buf = readModuleData(&moduleCommand->module); - auto trapResult = executeWASM(store, filename, buf->data, functionTypes, wasi, ®isteredInstanceMap); + auto trapResult = executeWASM(store, filename, buf->data, functionTypes, ®isteredInstanceMap); if (trapResult.exception) { std::string& errorMessage = trapResult.exception->message(); printf("Error: %s\n", errorMessage.c_str()); @@ -760,7 +759,7 @@ static void executeWAST(Store* store, const std::string& filename, const std::ve RELEASE_ASSERT_NOT_REACHED(); } auto buf = readModuleData(&tsm->module); - auto trapResult = executeWASM(store, filename, buf->data, functionTypes, wasi, ®isteredInstanceMap); + auto trapResult = executeWASM(store, filename, buf->data, functionTypes, ®isteredInstanceMap); RELEASE_ASSERT(trapResult.exception); std::string& s = trapResult.exception->message(); if (s.find(assertModuleUninstantiable->text) != 0) { @@ -808,7 +807,7 @@ static void executeWAST(Store* store, const std::string& filename, const std::ve } else { buf = dsm->data; } - auto trapResult = executeWASM(store, filename, buf, functionTypes, wasi); + auto trapResult = executeWASM(store, filename, buf, functionTypes); if (trapResult.exception == nullptr) { printf("Execute WASM returned nullptr (in wabt::CommandType::AssertInvalid case)\n"); printf("Expected exception:%s\n", assertModuleInvalid->text.data()); @@ -839,7 +838,7 @@ static void executeWAST(Store* store, const std::string& filename, const std::ve } else { buf = dsm->data; } - auto trapResult = executeWASM(store, filename, buf, functionTypes, wasi); + auto trapResult = executeWASM(store, filename, buf, functionTypes); if (trapResult.exception == nullptr) { printf("Execute WASM returned nullptr (in wabt::CommandType::AssertUnlinkable case)\n"); printf("Expected exception:%s\n", assertUnlinkable->text.data()); @@ -1036,14 +1035,14 @@ int main(int argc, char* argv[]) if (!argParser.exportToRun.empty()) { runExports(store, filePath, buf, argParser.exportToRun); } else { - auto trapResult = executeWASM(store, filePath, buf, functionTypes, wasi); + auto trapResult = executeWASM(store, filePath, buf, functionTypes); if (trapResult.exception) { fprintf(stderr, "Uncaught Exception: %s\n", trapResult.exception->message().data()); return -1; } } } else if (endsWith(filePath, "wat") || endsWith(filePath, "wast")) { - executeWAST(store, filePath, buf, functionTypes, wasi); + executeWAST(store, filePath, buf, functionTypes); } } else { printf("Cannot open file %s\n", filePath.data()); diff --git a/src/wasi/Fd.h b/src/wasi/Fd.h new file mode 100644 index 000000000..e27676868 --- /dev/null +++ b/src/wasi/Fd.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023-present Samsung Electronics Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Walrus { + +void WASI::fd_write(ExecutionState& state, Value* argv, Value* result, Instance* instance) +{ + uint32_t fd = argv[0].asI32(); + 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)); + result[1] = Value(static_cast(0)); + 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; + } + + uvwasi_size_t out_addr; + 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; +} + +} // namespace Walrus diff --git a/src/wasi/Wasi.cpp b/src/wasi/Wasi.cpp index 48a60a028..1f40bb4cd 100644 --- a/src/wasi/Wasi.cpp +++ b/src/wasi/Wasi.cpp @@ -15,11 +15,15 @@ */ #include "wasi/Wasi.h" +#include "wasi/Fd.h" // https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md namespace Walrus { +WASI::WasiFunc WASI::m_wasiFunctions[FuncEnd]; +uvwasi_t* WASI::m_uvwasi; + WASI::WasiFunc* WASI::find(std::string funcName) { for (unsigned i = 0; i < WasiFuncName::FuncEnd; ++i) { @@ -30,7 +34,30 @@ WASI::WasiFunc* WASI::find(std::string funcName) return nullptr; } -void WASI::proc_exit(ExecutionState& state, Value* argv, Value* result, void* data) +bool WASI::checkStr(Memory* memory, uint32_t memoryOffset, std::string& str) +{ + for (uint32_t i = memoryOffset; i < memory->sizeInByte(); ++i) { + if (memoryOffset >= memory->sizeInByte()) { + return false; + } else if (*reinterpret_cast(memory->buffer() + memoryOffset + i) == '\0') { + str = std::string(reinterpret_cast(memory->buffer() + memoryOffset)); + break; + } + } + + return true; +} + +bool WASI::checkMemOffset(Memory* memory, uint32_t memoryOffset, uint32_t length) +{ + if (memoryOffset + length >= memory->sizeInByte()) { + return false; + } + + return true; +} + +void WASI::proc_exit(ExecutionState& state, Value* argv, Value* result, Instance* instance) { ASSERT(argv[0].type() == Value::I32); exit(argv[0].asI32()); @@ -50,6 +77,24 @@ void WASI::fillWasiFuncTable() WASI::WASI() { fillWasiFuncTable(); + + uvwasi_t uvwasi; + WASI::m_uvwasi = reinterpret_cast(malloc(sizeof(uvwasi_t))); + + uvwasi_options_t init_options; + init_options.in = 0; + init_options.out = 1; + init_options.err = 2; + init_options.fd_table_size = 3; + init_options.argc = 0; + init_options.argv = nullptr; + init_options.envp = nullptr; + init_options.preopenc = 0; + init_options.preopen_socketc = 0; + init_options.allocator = nullptr; + + uvwasi_errno_t err = uvwasi_init(WASI::m_uvwasi, &init_options); + assert(err == UVWASI_ESUCCESS); } } // namespace Walrus diff --git a/src/wasi/Wasi.h b/src/wasi/Wasi.h index 78a5857da..f7d7be360 100644 --- a/src/wasi/Wasi.h +++ b/src/wasi/Wasi.h @@ -19,6 +19,9 @@ #include "runtime/Function.h" #include "runtime/ObjectType.h" #include "runtime/SpecTest.h" +#include "runtime/Memory.h" +#include "runtime/Instance.h" +#include namespace Walrus { @@ -112,22 +115,29 @@ class WASI { } wasi_errno_t; #undef TO_ENUM + typedef struct wasi_iovec { + uint8_t* buf; + uint32_t len; + } wasi_iovec_t; + // end of type definitions WASI(); ~WASI() { + ::uvwasi_destroy(m_uvwasi); } struct WasiFunc { std::string name; SpecTestFunctionTypes::Index functionType; - ImportedFunction::ImportedFunctionCallback ptr; + WasiFunction::WasiFunctionCallback ptr; }; #define FOR_EACH_WASI_FUNC(F) \ - F(proc_exit, I32R) + F(proc_exit, I32R) \ + F(fd_write, I32I32I32I32_RI32) enum WasiFuncName : size_t { #define DECLARE_FUNCTION(NAME, FUNCTYPE) NAME##FUNC, @@ -137,11 +147,15 @@ class WASI { }; void fillWasiFuncTable(); - WasiFunc* find(std::string funcName); + static WasiFunc* find(std::string funcName); + static bool checkStr(Memory* memory, uint32_t memoryOffset, std::string& str); + static bool checkMemOffset(Memory* memory, uint32_t memoryOffset, uint32_t length); - static void proc_exit(ExecutionState& state, Value* argv, Value* result, void* data); + static void proc_exit(ExecutionState& state, Value* argv, Value* result, Instance* instance); + static void fd_write(ExecutionState& state, Value* argv, Value* result, Instance* instance); - WasiFunc m_wasiFunctions[FuncEnd]; + static WasiFunc m_wasiFunctions[FuncEnd]; + static uvwasi_t* m_uvwasi; }; } // namespace Walrus diff --git a/test/wasi/hello_world.wast b/test/wasi/hello_world.wast new file mode 100644 index 000000000..49367b31d --- /dev/null +++ b/test/wasi/hello_world.wast @@ -0,0 +1,24 @@ +(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/third_party/uvwasi b/third_party/uvwasi new file mode 160000 index 000000000..de39e5f0e --- /dev/null +++ b/third_party/uvwasi @@ -0,0 +1 @@ +Subproject commit de39e5f0e926afcf2fa8b877053a81f5ae0df99f diff --git a/third_party/wabt/include/wabt/common.h b/third_party/wabt/include/wabt/common.h index a0ca2ea67..ef1610676 100644 --- a/third_party/wabt/include/wabt/common.h +++ b/third_party/wabt/include/wabt/common.h @@ -173,11 +173,16 @@ Dst WABT_VECTORCALL Bitcast(Src&& value) { return result; } +/* +This function caused build problems on windows, +probably because libuv implements a function with the same name. + template void ZeroMemory(T& v) { WABT_STATIC_ASSERT(std::is_pod::value); memset(&v, 0, sizeof(v)); } +*/ // Placement construct template diff --git a/third_party/wabt/src/binary-reader.cc b/third_party/wabt/src/binary-reader.cc index 4c3ebd8c7..ab5f82a1a 100644 --- a/third_party/wabt/src/binary-reader.cc +++ b/third_party/wabt/src/binary-reader.cc @@ -873,7 +873,8 @@ Result BinaryReader::ReadInstructions(bool stop_on_end, case Opcode::V128Const: { v128 value_bits; - ZeroMemory(value_bits); + WABT_STATIC_ASSERT(std::is_pod::value); + memset(&value_bits, 0, sizeof(v128)); CHECK_RESULT(ReadV128(&value_bits, "v128.const value")); CALLBACK(OnV128ConstExpr, value_bits); CALLBACK(OnOpcodeV128, value_bits);