Skip to content

Instantly share code, notes, and snippets.

@jfo
Last active August 16, 2018 03:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jfo/5c3c051a4090e604f8325e3fb4811d61 to your computer and use it in GitHub Desktop.
Save jfo/5c3c051a4090e604f8325e3fb4811d61 to your computer and use it in GitHub Desktop.
hoppetosse: I reread the gist, the only big thing I've left out is what I thought it was... you have to 1) build llvm from http://prereleases.llvm.org/6.0.0/ adding the DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly to CMake
then build zig where -DCMAKE_PREFIX_PATH is set to the install directory of that llvm
off of the llvm6 branch
and from there I think the gist is accurate

so many hoops to jump through but it works

looks like this:

zig build-obj  --release-fast --target-arch wasm32 --target-os freestanding thing.zig --output out.wasm
export fn doubler(x:i32) i32 {
    return x * 2;
}

and I just hardcoded the environ, since I couldn't figure out why it wasn't accepting it...

diff --git a/src/target.cpp b/src/target.cpp
index 69b1d6a8..d95817f8 100644
--- a/src/target.cpp
+++ b/src/target.cpp
@@ -503,10 +503,12 @@ void get_target_triple(Buf *triple, const ZigTarget *target) {
     get_arch_name(arch_name, &target->arch);
 
     buf_resize(triple, 0);
-    buf_appendf(triple, "%s-%s-%s-%s", arch_name,
+    buf_appendf(triple, "%s-%s-%s-wasm", arch_name,
             ZigLLVMGetVendorTypeName(target->vendor),
-            ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)),
-            ZigLLVMGetEnvironmentTypeName(target->env_type));
+            ZigLLVMGetOSTypeName(get_llvm_os_type(target->os))
+        );
+
+            /* ZigLLVMGetEnvironmentTypeName(target->env_type)); */
 }
 
 static bool is_os_darwin(ZigTarget *target) {

That gives me a binary that I can use binaryen's wasm-dis on to see:

(module
 (type $0 (func (param i32) (result i32)))
 (import "env" "__linear_memory" (memory $0 0))
 (import "env" "__indirect_function_table" (table 0 anyfunc))
 (export "doubler" (func $doubler))
 (func $doubler (; 0 ;) (type $0) (param $var$0 i32) (result i32)
  (i32.shl
   (get_local $var$0)
   (i32.const 1)
  )
 )
 ;; custom section "linking", size 0
)

then the instantiation:

fetch('out.wasm').then blah blah res
WebAssembly.instantiateStreaming(res, {
  env: {
    __linear_memory: new WebAssembly.Memory({initial: 10}),
    __indirect_function_table: new WebAssembly.Table({element:'anyfunc', initial: 10})
  }
}).then(function (wasmModule) {
    return wasmModule.instance.exports;
});

And

const {doubler} = require('./out.wasm');
console.log(doubler(4));

prints 8 in the browser.

There is a lot of work to do but I'm super jazzed.

@jfo
Copy link
Author

jfo commented Apr 10, 2018

This is now out of date,

If llvm is compiled with DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly, this should work out of the box with something along the lines of

zig build-obj --release-fast --target-arch wasm32 --target-os freestanding thing.zig --output out.wasm

the goal in the next half year would be to flesh out the std lib and polyfilling functionality b/t the js runtime (as "os") and the wasm code.

@andriytyurnikov
Copy link

@jfo what I get is

unable to create target based on: wasm32-unknown-unknown-wasm
Abort trap: 6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment