Add emscripten_lib target

extensions
Volodymyr Shymanskyy 4 years ago
parent 90fa7f5639
commit 490bf0c9d6

@ -30,12 +30,18 @@ if(CLANG_CL)
set(CMAKE_LINKER "lld-link")
endif()
if(EMSCRIPTEN)
if(EMSCRIPTEN OR EMSCRIPTEN_LIB)
set(CMAKE_C_COMPILER "emcc")
set(CMAKE_CXX_COMPILER "em++")
set(OUT_FILE "wasm3.html")
set(APP_DIR "platforms/emscripten")
if (EMSCRIPTEN_LIB)
set(APP_DIR "platforms/emscripten_lib")
set(OUT_FILE "wasm3.wasm")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s STANDALONE_WASM")
else()
set(APP_DIR "platforms/emscripten")
set(OUT_FILE "wasm3.html")
endif()
endif()
# Detect WasiEnv
@ -77,29 +83,36 @@ add_executable(${OUT_FILE} ${app_srcs})
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG=1")
if(EMSCRIPTEN)
set(CMAKE_C_FLAGS_RELEASE "-O2 -flto -Wfatal-errors")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2 --lto-O3 --closure 1 --strip-all --gc-sections") # --emrun
if(WASM_TCO)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Xclang -target-feature -Xclang +tail-call")
if(EMSCRIPTEN OR EMSCRIPTEN_LIB)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s GLOBAL_BASE=1024 -s TOTAL_STACK=2MB -s INITIAL_MEMORY=4MB -s ALLOW_MEMORY_GROWTH")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s EXPORTED_FUNCTIONS='[\"_malloc\",\"_free\"]'")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -flto -Wfatal-errors -s ASSERTIONS=0")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} --strip-all --gc-sections")
if(WASM_EXT)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mbulk-memory -mnontrapping-fptoint -msign-ext -mtail-call")
endif()
elseif(WASIENV)
if(BUILD_WASI_SUPPORT)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasMetaWASI -Dd_m3HasTracer")
endif()
set(CMAKE_C_FLAGS_RELEASE "-O3 -Wfatal-errors -fomit-frame-pointer -fno-stack-check -fno-stack-protector")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -Wfatal-errors -fomit-frame-pointer -fno-stack-check -fno-stack-protector")
# TODO: LTO breaks wasm imports currently:
# https://www.mail-archive.com/llvm-bugs@lists.llvm.org/msg36273.html
#-flto -Wl,--lto-O3
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,stack-size=8388608")
elseif(WIN32)
if(BUILD_WASI_SUPPORT)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasWASI")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasWASI -Dd_m3HasTracer")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /WX- /diagnostics:column")
@ -145,6 +158,7 @@ else()
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-O3")
target_link_libraries(${OUT_FILE} m)
endif()
check_ipo_supported(RESULT result)

@ -0,0 +1,57 @@
//
// Wasm3 - high performance WebAssembly interpreter written in C.
//
// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy.
// All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <emscripten.h>
#include "wasm3.h"
#include "m3_env.h"
IM3Environment env;
EMSCRIPTEN_KEEPALIVE
void init() {
env = m3_NewEnvironment ();
if (!env) return;
}
EMSCRIPTEN_KEEPALIVE
IM3Runtime new_runtime() {
return m3_NewRuntime (env, 64*1024, NULL);
}
EMSCRIPTEN_KEEPALIVE
void free_runtime(IM3Runtime runtime) {
m3_FreeRuntime (runtime);
}
EMSCRIPTEN_KEEPALIVE
void load(IM3Runtime runtime, uint8_t* wasm, size_t fsize) {
M3Result result = m3Err_none;
IM3Module module;
result = m3_ParseModule (env, &module, wasm, fsize);
if (result) return;
result = m3_LoadModule (runtime, module);
if (result) return;
}
EMSCRIPTEN_KEEPALIVE
uint32_t call(IM3Runtime runtime, const char* name, int argc, const char** argv) {
M3Result result = m3Err_none;
IM3Function f;
result = m3_FindFunction (&f, runtime, name);
if (result) return -1;
result = m3_CallWithArgs (f, argc, argv);
if (result) return -2;
return *(uint64_t*)(runtime->stack);
}

@ -0,0 +1,139 @@
'use strict';
/*
Node.js
-------
node --v8-options | grep -A1 wasm
--print_wasm_code --code-comments
--wasm_interpret_all --trace_wasm_interpreter
SpiderMonkey
------------
export PATH=/opt/jsshell/:$PATH
js --help | grep wasm
--wasm-compiler=baseline/ion/cranelift/baseline+ion/baseline+cranelift
--wasm-verbose
--ion-full-warmup-threshold=1
*/
const isNodeJS = (typeof(process) != 'undefined');
function encode(str) {
var Len = str.length, resPos = -1;
var resArr = new Uint8Array(Len * 3);
for (var i = 0; i !== Len; i += 1) {
var point = str.charCodeAt(i);
if (point <= 0x007f) {
resArr[resPos += 1] = point;
}
}
return resArr.subarray(0, resPos + 1);
}
if (isNodeJS) {
var scriptArgs = process.argv.slice(2);
const fs = require('fs');
var readFile = (fn) => new Uint8Array(fs.readFileSync(fn));
} else {
var readFile = (fn) => read(fn, 'binary');
}
const env = {
__memory_base: 0,
__table_base: 0,
"env": {
"emscripten_notify_memory_growth": function() {},
"emscripten_get_sbrk_ptr": function() {},
},
"wasi_snapshot_preview1": {
"fd_close": function() {},
"fd_seek": function() {},
"fd_write": function() { return -1; },
"proc_exit": function() {}
}
}
var instance;
//let encoder = new TextEncoder('utf-8');
function strToMem(s) {
const data = encode(s);
const ptr = instance.exports.malloc(data.length+1);
const buf = new Uint8Array(instance.exports.memory.buffer, ptr, data.length+1);
buf.set(data)
buf[data.length] = 0;
return ptr;
}
function bufToMem(data) {
const ptr = instance.exports.malloc(data.length);
const buf = new Uint8Array(instance.exports.memory.buffer, ptr, data.length);
buf.set(data)
return ptr;
}
function new_runtime() {
return instance.exports.new_runtime();
}
function free_runtime(runtime) {
instance.exports.free_runtime(runtime);
}
function load(runtime, buff) {
const ptr = bufToMem(buff);
instance.exports.load(runtime, ptr, buff.length);
}
function call(runtime, fname, args) {
const namePtr = strToMem(fname)
const argsCnt = args.length;
const argsPtr = instance.exports.malloc(argsCnt*4);
const argsArray = new Uint32Array(
instance.exports.memory.buffer,
argsPtr, argsCnt
);
args.forEach((item, idx) => {
argsArray[idx] = strToMem(item.toString());
})
return instance.exports.call(runtime, namePtr, argsCnt, argsPtr);
}
/* TODO:
* - callback/hook exported function calls
*
*/
async function main() {
const FILE = scriptArgs[0];
const FUNC = scriptArgs[1];
const ARGS = scriptArgs.slice(2);
for (let i=0; i<25000; i++) {
let rt = new_runtime();
load(rt, readFile(FILE));
let result = call(rt, FUNC, [1]);
//console.log(i, result);
free_runtime(rt);
}
}
try {
WebAssembly.instantiate(readFile('wasm3.wasm'), env).then(result => {
instance = result.instance;
instance.exports.init();
main();
console.log(`Memory size: ${instance.exports.memory.buffer.byteLength}`);
})
} catch (e) {
console.log(JSON.stringify(e.message));
}
Loading…
Cancel
Save