-
-
Save AlexAltea/78e8da45e20fdb1bf2afb8816de53bae to your computer and use it in GitHub Desktop.
Minimal WASM JIT proof-of-concept
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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