Skip to content

Instantly share code, notes, and snippets.

@AlexAltea
Created February 12, 2019 22:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AlexAltea/78e8da45e20fdb1bf2afb8816de53bae to your computer and use it in GitHub Desktop.
Save AlexAltea/78e8da45e20fdb1bf2afb8816de53bae to your computer and use it in GitHub Desktop.
Minimal WASM JIT proof-of-concept
#include <binaryen-c.h>
#include <emscripten.h>
#include <stdio.h>
typedef int (*iii_t)(int, int);
int adder_func(int a, int b) {
return a + b;
}
int main() {
BinaryenModuleRef m = BinaryenModuleCreate();
// Create a function type for: i32 (i32, i32)
BinaryenType params[2] = { BinaryenTypeInt32(), BinaryenTypeInt32() };
BinaryenFunctionTypeRef iii = BinaryenAddFunctionType(m, "iii", BinaryenTypeInt32(), params, 2);
// Get the 0 and 1 arguments, and forward them to `func`
BinaryenExpressionRef adder_ptr, adder_res;
BinaryenExpressionRef operands[2];
operands[0] = BinaryenGetLocal(m, 0, BinaryenTypeInt32());
operands[1] = BinaryenGetLocal(m, 1, BinaryenTypeInt32());
adder_ptr = BinaryenConst(m, BinaryenLiteralInt32((uintptr_t)adder_func));
adder_res = BinaryenCallIndirect(m, adder_ptr, operands, 2, "iii");
// Create the wrapper function (no local variables, no basic blocks)
BinaryenAddFunction(m, "adder_wrapper", iii, NULL, 0, adder_res);
BinaryenAddFunctionExport(m, "adder_wrapper", "adder_wrapper");
BinaryenAddMemoryImport(m, NULL, "env", "memory", 0);
BinaryenAddTableImport(m, NULL, "env", "table");
// Print module and generate bytecode
BinaryenModuleAllocateAndWriteResult result;
assert(BinaryenModuleValidate(m));
BinaryenModuleOptimize(m);
BinaryenModulePrint(m);
result = BinaryenModuleAllocateAndWrite(m, NULL);
// Link module
uint32_t adder_wrapper_index = EM_ASM_INT({
var jit_binary = new Uint8Array(wasmMemory.buffer, $0, $1);
var jit_module = new WebAssembly.Module(jit_binary);
var jit_instance = new WebAssembly.Instance(jit_module, {
env: {
memory: wasmMemory,
table: wasmTable,
}
});
var adder_wrapper = jit_instance.exports["adder_wrapper"];
var adder_wrapper_index = addWasmFunction(adder_wrapper);
return adder_wrapper_index;
}, result.binary, result.binaryBytes);
// Clean up the module, which owns all objects above, and free the bytecode
BinaryenModuleDispose(m);
free(result.binary);
// Execute code!
int a = 3;
int b = 4;
iii_t adder_wrapper = (iii_t)adder_wrapper_index;
printf("adder_wrapper(%d, %d) = %d\n", a, b, adder_wrapper(a, b));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment