-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwebassembly.jl
121 lines (102 loc) · 2.75 KB
/
webassembly.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# ---
# jupyter:
# jupytext:
# formats: ipynb,jl:light
# text_representation:
# extension: .jl
# format_name: light
# format_version: '1.5'
# jupytext_version: 1.6.0
# kernelspec:
# display_name: Julia 1.5.3
# language: julia
# name: julia-1.5
# ---
# # WASM with Julia
#
# - This notebook provides the reader with a demo that uses a Julia package called WebAssembly.jl to generate a .wasm file and call on your device
#
# ## Install Packages
#
# - Install WebAssembly.jl (master branch required) and IRTools.jl
#
#
# ```julia
# julia> ENV["PYTHON"]=Sys.which("python3")
# julia> using Pkg
# julia> pkg"add WebAssembly#master"
# julia> Pkg.add(["IRTools", "PyCall"])
# ```
#
# - Note that we've installed PyCall.jl for convenience to run wasm file locally.
#
# ## Install wasmer
#
# To run wasm file locally, install [wasmer](https://github.com/wasmerio/python-ext-wasm) from PyPI in advance via
#
#
#
# ```console
# $ pip3 install wasmer
# ```
# ## Import Packages
#
# OK let's get started
using WebAssembly
using WebAssembly: f64, irfunc # i32 and so on
using IRTools.All
using PyCall
# ## generate `.wasm` for f(x) = x + x
#
# - In this notebook, we would like to implement simple function that takes one argument and return double value of the argument.
f(x) = x + x # define function
@code_ir f(3.) # check IR
# ## Construct IR for WASM
#
# - Let's generate an IR(intermediate representation) similar to the above form.
twice = let
ir = IR()
x = argument!(ir, f64)
r = push!(ir, stmt(xcall(f64.add, x, x), type=f64))
return!(ir, r)
end
# ## Generate `.wasm` file
#
# - Here we create the wasm file so that we can call the function named `twice`.
#
# +
funcname = :twice
func = irfunc(funcname, twice)
mod = WebAssembly.Module(
funcs=[func],
exports=[WebAssembly.Export(funcname, funcname, :func)]
)
WebAssembly.binary(mod, "$(funcname).wasm")
# -
# # Disassemble wasm
run(`$(WebAssembly.Binaryen.wasm_dis) $(funcname).wasm`);
# # Call wasm file from Python
#
# - Let's call the program stored in the wasm file. We'll use Python as a lamp for Aladdin.
# +
pycode = """
from wasmer import Instance
def run_wasm(*args):
wasm_bytes = open("$(funcname).wasm", 'rb').read()
instance = Instance(wasm_bytes)
res = instance.exports.$(funcname)(*args)
return res
"""
pyfile = string(funcname) * ".py"
open(pyfile,"w") do f
print(f, pycode)
end
# -
pushfirst!(PyVector(pyimport("sys")."path"), @__DIR__)
pymodule = pyimport(funcname)
pymodule.run_wasm(3.) # 3. + 3. should be 6.0
# # References
#
# - [MikeInnes/WebAssembly.jl](https://github.com/MikeInnes/WebAssembly.jl)
# - [FluxML/IRTools.jl](https://github.com/FluxML/IRTools.jl)
# - [wasmerio/python-ext-wasm](https://github.com/wasmerio/python-ext-wasm)