Skip to content

Instantly share code, notes, and snippets.

@AmaanC
Last active November 15, 2017 07:32
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 AmaanC/2731b753c50c177c2fbe583eae34fa43 to your computer and use it in GitHub Desktop.
Save AmaanC/2731b753c50c177c2fbe583eae34fa43 to your computer and use it in GitHub Desktop.
Adding support for WebAssembly's call_indirect operator directly in your C code by compiling LLVM IR with your C code through emscripten

Making call_indirect operator accessible in C

  • emcc supports compiling .ll and .bc files
  • Based on LLVM's tests, we can have LLVM IR generate a call_indirect function (with several types of function signatures of parameters)
target datalayout = "e-p:32:32-i64:64-v128:32:128-n32-S128"
target triple = "asmjs-unknown-emscripten"
; https://github.com/llvm-mirror/llvm/blob/45ed11f7a623932117ee4a3deb540e3869c38fe4/test/CodeGen/WebAssembly/call.ll#L84-L92
define void @call_indirect(void ()* %callee) {
call void %callee()
ret void
}
<script src='loader.js'></script>
<h1>Check the console</h1>
let imports = {
env: {
memory: WebAssembly.Memory({ initial: 256 }),
memoryBase: 0,
table: WebAssembly.Table({ initial: 1, element: 'anyfunc' }),
tableBase: 0,
abort: () => {
debugger;
},
_call_js: () => {
console.log('main.c called call_js');
debugger;
}
}
};
fetch('main.wasm').then((resp) => {
return resp.arrayBuffer();
}).then((buffer) => {
return WebAssembly.instantiate(
buffer,
imports
);
}).then(({instance, module}) => {
imports.env.table.set(0, instance.exports._call_js_log);
instance.exports._main();
});
void call_indirect(int index);
void call_js();
// WebAssembly#Table's can only have Exported Function Exotic Objects
// https://github.com/WebAssembly/design/blob/master/JS.md#webassemblytable-objects
// We'll put call_js_log in the Table then, and call_indirect(0) should call it
void call_js_log()
{
call_js();
}
int main()
{
// Assumes the environment sets the default Table up with an entry at 0
call_indirect(0);
return 0;
}
main.wasm: main.c call-indirect.ll
emcc $^ -o $@ \
-O3 \
-s LEGALIZE_JS_FFI=0 \
-s WASM=1 -s SIDE_MODULE=1 \
-g4
.PHONY: serve
serve: main.wasm loader.js index.html
python3 -m http.server 8888
echo "Visit http://localhost:8888/"
.PHONE: clean
clean:
rm main.wasm
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment