Skip to content

Commit

Permalink
Implement emscripten compability
Browse files Browse the repository at this point in the history
Change runExports so that wasi imports can be used.
Improve fd_write so that emscipten compiled programs can be used.
Also add example programs.
Also update build file to use not use incorrect flags on windows.

Signed-off-by: Adam Laszlo Kulcsar <kuladam@inf.u-szeged.hu>
  • Loading branch information
kulcsaradam committed Nov 8, 2023
1 parent a899ce5 commit 16d95a3
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 67 deletions.
18 changes: 9 additions & 9 deletions build/wasi.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
59 changes: 50 additions & 9 deletions src/shell/Shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<RunData*>(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);
}
Expand Down Expand Up @@ -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<uint8_t>& src, std::string& exportToRun)
static void runExports(Store* store, const std::string& filename, const std::vector<uint8_t>& src, std::string& exportToRun, SpecTestFunctionTypes& functionTypes)
{
auto parseResult = WASMParser::parseBinary(store, filename, src.data(), src.size());

Expand All @@ -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<FunctionType*>(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<RunData*>(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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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();
Expand Down
12 changes: 4 additions & 8 deletions src/wasi/Fd.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,21 @@ 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<int16_t>(WASI::wasi_errno::inval));
result[1] = Value(static_cast<int32_t>(0));
return;
}

uint32_t offset = *reinterpret_cast<uint32_t*>(instance->memory(0)->buffer() + iovptr);
wasi_iovs.buf = reinterpret_cast<uint8_t*>(instance->memory(0)->buffer() + offset);
wasi_iovs.len = *reinterpret_cast<uint32_t*>(instance->memory(0)->buffer() + iovptr + sizeof(uvwasi_size_t));

std::vector<uvwasi_ciovec_t> 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<uint32_t*>(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<int16_t>(uvwasi_fd_write(WASI::m_uvwasi, fd, iovs.data(), iovs.size(), &out_addr)));
*(instance->memory(0)->buffer() + out) = out_addr;
}
Expand Down
6 changes: 0 additions & 6 deletions src/wasi/Wasi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
24 changes: 0 additions & 24 deletions test/wasi/hello_world.wast

This file was deleted.

14 changes: 14 additions & 0 deletions test/wasi/hello_world/hello_world.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <stdio.h>
#include <stdint.h>

/* 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;
}
Binary file added test/wasi/hello_world/hello_world.wasm
Binary file not shown.
23 changes: 23 additions & 0 deletions test/wasi/hello_world/hello_world.wast
Original file line number Diff line number Diff line change
@@ -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"))
11 changes: 0 additions & 11 deletions test/wasi/proc_exit.wast

This file was deleted.

7 changes: 7 additions & 0 deletions test/wasi/proc_exit/proc_exit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "stdlib.h"

int main()
{
exit(0);
return 0;
}
Binary file added test/wasi/proc_exit/proc_exit.wasm
Binary file not shown.
11 changes: 11 additions & 0 deletions test/wasi/proc_exit/proc_exit.wast
Original file line number Diff line number Diff line change
@@ -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"))

0 comments on commit 16d95a3

Please sign in to comment.