wardite 0.5.1 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/Steepfile +1 -0
- data/exe/wardite +11 -5
- data/lib/wardite/instruction.rb +7 -9
- data/lib/wardite/load.rb +14 -9
- data/lib/wardite/revisitor.rb +1 -1
- data/lib/wardite/value.rb +28 -23
- data/lib/wardite/version.rb +1 -1
- data/lib/wardite/wasi/consts.rb +129 -0
- data/lib/wardite/wasi.rb +268 -7
- data/lib/wardite/wasm_module.rb +53 -0
- data/lib/wardite.rb +68 -40
- data/misc/bench-value.rb +25 -0
- data/misc/slides/fib.c +4 -0
- data/misc/slides/fib.html +13 -0
- data/misc/slides/image-1.png +0 -0
- data/misc/slides/image-2.png +0 -0
- data/misc/slides/image.png +0 -0
- data/misc/slides/tokyo12.html +614 -0
- data/misc/slides/tokyo12.md +624 -0
- data/sig/fcntl.rbs +7 -0
- data/sig/generated/wardite/leb128.rbs +1 -1
- data/sig/generated/wardite/load.rbs +2 -2
- data/sig/generated/wardite/value.rbs +12 -10
- data/sig/generated/wardite/wasi/consts.rbs +137 -0
- data/sig/generated/wardite/wasi.rbs +62 -5
- data/sig/generated/wardite/wasm_module.rbs +42 -0
- data/sig/generated/wardite.rbs +24 -9
- metadata +16 -7
- data/examples/add.wasm +0 -0
data/lib/wardite/wasi.rb
CHANGED
@@ -1,16 +1,161 @@
|
|
1
1
|
# rbs_inline: enabled
|
2
|
+
|
3
|
+
require "wardite/wasm_module"
|
4
|
+
require "wardite/wasi/consts"
|
5
|
+
require "securerandom"
|
6
|
+
require "fcntl"
|
7
|
+
|
2
8
|
module Wardite
|
3
9
|
class WasiSnapshotPreview1
|
4
10
|
include ValueHelper
|
11
|
+
include WasmModule
|
5
12
|
|
6
|
-
attr_accessor :fd_table #: Array[IO]
|
13
|
+
attr_accessor :fd_table #: Array[(IO|File)]
|
14
|
+
attr_accessor :argv #: Array[String]
|
7
15
|
|
8
|
-
|
16
|
+
# @rbs argv: Array[String]
|
17
|
+
# @rbs return: void
|
18
|
+
def initialize(argv: [])
|
9
19
|
@fd_table = [
|
10
20
|
STDIN,
|
11
21
|
STDOUT,
|
12
22
|
STDERR,
|
13
23
|
]
|
24
|
+
@argv = argv
|
25
|
+
end
|
26
|
+
|
27
|
+
# @rbs store: Store
|
28
|
+
# @rbs args: Array[wasmValue]
|
29
|
+
# @rbs return: Object
|
30
|
+
def args_get(store, args)
|
31
|
+
arg_offsets_p = args[0].value
|
32
|
+
arg_data_buf_p = args[1].value
|
33
|
+
if !arg_data_buf_p.is_a?(Integer)
|
34
|
+
raise ArgumentError, "invalid type of args: #{args.inspect}"
|
35
|
+
end
|
36
|
+
|
37
|
+
arg_offsets = [] #: Array[Integer]
|
38
|
+
arg_data_slice = [] #: Array[String]
|
39
|
+
current_offset = arg_data_buf_p
|
40
|
+
@argv.each do |arg|
|
41
|
+
arg_offsets << current_offset
|
42
|
+
arg_data_slice << arg
|
43
|
+
current_offset += arg.size + 1
|
44
|
+
end
|
45
|
+
arg_data = arg_data_slice.join("\0") + "\0"
|
46
|
+
|
47
|
+
memory = store.memories[0]
|
48
|
+
memory.data[arg_data_buf_p...(arg_data_buf_p + arg_data.size)] = arg_data
|
49
|
+
|
50
|
+
arg_offsets.each_with_index do |offset, i|
|
51
|
+
data_begin = arg_offsets_p + i * 4
|
52
|
+
memory.data[data_begin...(data_begin + 4)] = [offset].pack("I!")
|
53
|
+
end
|
54
|
+
|
55
|
+
0
|
56
|
+
end
|
57
|
+
|
58
|
+
# @rbs store: Store
|
59
|
+
# @rbs args: Array[wasmValue]
|
60
|
+
# @rbs return: Object
|
61
|
+
def args_sizes_get(store, args)
|
62
|
+
argc_p = args[0].value
|
63
|
+
arglen_p = args[1].value
|
64
|
+
argc = @argv.length
|
65
|
+
arglen = @argv.map{|arg| arg.size + 1}.sum
|
66
|
+
|
67
|
+
memory = store.memories[0]
|
68
|
+
memory.data[argc_p...(argc_p+4)] = [argc].pack("I!")
|
69
|
+
memory.data[arglen_p...(arglen_p+4)] = [arglen].pack("I!")
|
70
|
+
0
|
71
|
+
end
|
72
|
+
|
73
|
+
# @rbs store: Store
|
74
|
+
# @rbs args: Array[wasmValue]
|
75
|
+
# @rbs return: Object
|
76
|
+
def environ_sizes_get(store, args)
|
77
|
+
envc_p = args[0].value
|
78
|
+
envlen_p = args[1].value
|
79
|
+
envc = ENV.length
|
80
|
+
envlen = ENV.map{|k,v| k.size + v.size + 1}.sum
|
81
|
+
|
82
|
+
memory = store.memories[0]
|
83
|
+
memory.data[envc_p...(envc_p+4)] = [envc].pack("I!")
|
84
|
+
memory.data[envlen_p...(envlen_p+4)] = [envlen].pack("I!")
|
85
|
+
0
|
86
|
+
end
|
87
|
+
|
88
|
+
# @rbs store: Store
|
89
|
+
# @rbs args: Array[wasmValue]
|
90
|
+
# @rbs return: Object
|
91
|
+
def environ_get(store, args)
|
92
|
+
environ_offsets_p = args[0].value
|
93
|
+
environ_data_buf_p = args[1].value
|
94
|
+
if !environ_data_buf_p.is_a?(Integer)
|
95
|
+
raise ArgumentError, "invalid type of args: #{args.inspect}"
|
96
|
+
end
|
97
|
+
|
98
|
+
environ_offsets = [] #: Array[Integer]
|
99
|
+
environ_data_slice = [] #: Array[String]
|
100
|
+
current_offset = environ_data_buf_p
|
101
|
+
ENV.each do |k, v|
|
102
|
+
environ_offsets << current_offset
|
103
|
+
environ_data_slice << "#{k}=#{v}"
|
104
|
+
current_offset += "#{k}=#{v}".size + 1
|
105
|
+
end
|
106
|
+
environ_data = environ_data_slice.join("\0") + "\0"
|
107
|
+
|
108
|
+
memory = store.memories[0]
|
109
|
+
memory.data[environ_data_buf_p...(environ_data_buf_p + environ_data.size)] = environ_data
|
110
|
+
|
111
|
+
environ_offsets.each_with_index do |offset, i|
|
112
|
+
data_begin = environ_offsets_p + i * 4
|
113
|
+
memory.data[data_begin...(data_begin + 4)] = [offset].pack("I!")
|
114
|
+
end
|
115
|
+
|
116
|
+
0
|
117
|
+
end
|
118
|
+
|
119
|
+
# @rbs store: Store
|
120
|
+
# @rbs args: Array[wasmValue]
|
121
|
+
# @rbs return: Object
|
122
|
+
def clock_time_get(store, args)
|
123
|
+
clock_id = args[0].value
|
124
|
+
# we dont use precision...
|
125
|
+
_precision = args[1].value
|
126
|
+
timebuf64 = args[2].value
|
127
|
+
if clock_id != 0 # - CLOCKID_REALTIME
|
128
|
+
# raise NotImplementedError, "CLOCKID_REALTIME is an only supported id"
|
129
|
+
return -255
|
130
|
+
end
|
131
|
+
# timestamp in nanoseconds
|
132
|
+
now = Time.now.to_i * 1_000_000
|
133
|
+
|
134
|
+
memory = store.memories[0]
|
135
|
+
now_packed = [now].pack("Q!")
|
136
|
+
memory.data[timebuf64...(timebuf64+8)] = now_packed
|
137
|
+
0
|
138
|
+
end
|
139
|
+
|
140
|
+
# @rbs store: Store
|
141
|
+
# @rbs args: Array[wasmValue]
|
142
|
+
# @rbs return: Object
|
143
|
+
def fd_prestat_get(store, args)
|
144
|
+
fd = args[0].value.to_i
|
145
|
+
prestat_offset = args[1].value.to_i
|
146
|
+
if fd >= @fd_table.size
|
147
|
+
return Wasi::EBADF
|
148
|
+
end
|
149
|
+
file = @fd_table[fd]
|
150
|
+
if !file.is_a?(File)
|
151
|
+
return Wasi::EBADF
|
152
|
+
end
|
153
|
+
name = file.path
|
154
|
+
memory = store.memories[0]
|
155
|
+
# Zero-value 8-bit tag, and 3-byte zero-value padding
|
156
|
+
memory.data[prestat_offset...(prestat_offset+4)] = [0].pack("I!")
|
157
|
+
memory.data[(prestat_offset+4)...(prestat_offset+8)] = [name.size].pack("I!")
|
158
|
+
0
|
14
159
|
end
|
15
160
|
|
16
161
|
# @rbs store: Store
|
@@ -29,6 +174,7 @@ module Wardite
|
|
29
174
|
raise Wardite::ArgumentError, "args too short"
|
30
175
|
end
|
31
176
|
file = self.fd_table[fd]
|
177
|
+
return Wasi::EBADF if !file
|
32
178
|
memory = store.memories[0]
|
33
179
|
nwritten = 0
|
34
180
|
iovs_len.times do
|
@@ -45,11 +191,126 @@ module Wardite
|
|
45
191
|
0
|
46
192
|
end
|
47
193
|
|
48
|
-
# @rbs
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
194
|
+
# @rbs store: Store
|
195
|
+
# @rbs args: Array[wasmValue]
|
196
|
+
# @rbs return: Object
|
197
|
+
def fd_read(store, args)
|
198
|
+
iargs = args.map do |elm|
|
199
|
+
if elm.is_a?(I32)
|
200
|
+
elm.value
|
201
|
+
else
|
202
|
+
raise Wardite::ArgumentError, "invalid type of args: #{args.inspect}"
|
203
|
+
end
|
204
|
+
end #: Array[Integer]
|
205
|
+
fd, iovs, iovs_len, rp = *iargs
|
206
|
+
if !fd || !iovs || !iovs_len || !rp
|
207
|
+
raise Wardite::ArgumentError, "args too short"
|
208
|
+
end
|
209
|
+
file = self.fd_table[fd]
|
210
|
+
return Wasi::EBADF if !file
|
211
|
+
memory = store.memories[0]
|
212
|
+
nread = 0
|
213
|
+
|
214
|
+
iovs_len.times do
|
215
|
+
start = unpack_le_int(memory.data[iovs...(iovs+4)])
|
216
|
+
iovs += 4
|
217
|
+
slen = unpack_le_int(memory.data[iovs...(iovs+4)])
|
218
|
+
iovs += 4
|
219
|
+
buf = file.read(slen)
|
220
|
+
if !buf
|
221
|
+
return Wasi::EFAULT
|
222
|
+
end
|
223
|
+
memory.data[start...(start+slen)] = buf
|
224
|
+
nread += slen
|
225
|
+
end
|
226
|
+
|
227
|
+
memory.data[rp...(rp+4)] = [nread].pack("I!")
|
228
|
+
0
|
229
|
+
end
|
230
|
+
|
231
|
+
# @rbs store: Store
|
232
|
+
# @rbs args: Array[wasmValue]
|
233
|
+
# @rbs return: Object
|
234
|
+
def fd_fdstat_get(store, args)
|
235
|
+
fd = args[0].value.to_i
|
236
|
+
fdstat_offset = args[1].value.to_i
|
237
|
+
if fd >= @fd_table.size
|
238
|
+
return Wasi::EBADF
|
239
|
+
end
|
240
|
+
file = @fd_table[fd]
|
241
|
+
fdflags = 0
|
242
|
+
if file.is_a?(IO)
|
243
|
+
fdflags |= Wasi::FD_APPEND
|
244
|
+
else
|
245
|
+
if (Fcntl::O_APPEND & file.fcntl(Fcntl::F_GETFL, 0)) != 0
|
246
|
+
fdflags |= Wasi::FD_APPEND
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
if (Fcntl::O_NONBLOCK & file.fcntl(Fcntl::F_GETFL, 0)) != 0
|
251
|
+
fdflags |= Wasi::FD_NONBLOCK
|
252
|
+
end
|
253
|
+
|
254
|
+
stat = file.stat #: File::Stat
|
255
|
+
ftype = Wasi.to_ftype(stat.ftype)
|
256
|
+
|
257
|
+
fs_right_base = 0
|
258
|
+
fs_right_inheriting = 0
|
259
|
+
|
260
|
+
case ftype
|
261
|
+
when Wasi::FILETYPE_DIRECTORY
|
262
|
+
fs_right_base = Wasi::RIGHT_DIR_RIGHT_BASE
|
263
|
+
fs_right_inheriting = Wasi::RIGHT_FILE_RIGHT_BASE | Wasi::RIGHT_DIR_RIGHT_BASE
|
264
|
+
when Wasi::FILETYPE_CHARACTER_DEVICE
|
265
|
+
fs_right_base = Wasi::RIGHT_FILE_RIGHT_BASE & \
|
266
|
+
(~Wasi::RIGHT_FD_SEEK) & (~Wasi::RIGHT_FD_TELL)
|
267
|
+
else
|
268
|
+
fs_right_base = Wasi::RIGHT_FILE_RIGHT_BASE
|
269
|
+
end
|
270
|
+
|
271
|
+
memory = store.memories[0]
|
272
|
+
|
273
|
+
binformat = [fdflags, ftype, 0, 0, 0, 0, fs_right_base, fs_right_inheriting]
|
274
|
+
.pack("SSC4QQ")
|
275
|
+
memory.data[fdstat_offset...(fdstat_offset+binformat.size)] = binformat
|
276
|
+
0
|
277
|
+
end
|
278
|
+
|
279
|
+
# @rbs store: Store
|
280
|
+
# @rbs args: Array[wasmValue]
|
281
|
+
# @rbs return: Object
|
282
|
+
def fd_filestat_get(store, args)
|
283
|
+
fd = args[0].value.to_i
|
284
|
+
filestat_offset = args[1].value.to_i
|
285
|
+
if fd >= @fd_table.size
|
286
|
+
return Wasi::EBADF
|
287
|
+
end
|
288
|
+
file = @fd_table[fd]
|
289
|
+
stat = file.stat #: File::Stat
|
290
|
+
memory = store.memories[0]
|
291
|
+
binformat = [stat.dev, stat.ino, Wasi.to_ftype(stat.ftype), stat.nlink, stat.size, stat.atime.to_i, stat.mtime.to_i, stat.ctime.to_i].pack("Q8")
|
292
|
+
memory.data[filestat_offset...(filestat_offset+binformat.size)] = binformat
|
293
|
+
0
|
294
|
+
end
|
295
|
+
|
296
|
+
# @rbs store: Store
|
297
|
+
# @rbs args: Array[wasmValue]
|
298
|
+
# @rbs return: Object
|
299
|
+
def proc_exit(store, args)
|
300
|
+
exit_code = args[0].value
|
301
|
+
exit(exit_code)
|
302
|
+
end
|
303
|
+
|
304
|
+
# @rbs store: Store
|
305
|
+
# @rbs args: Array[wasmValue]
|
306
|
+
# @rbs return: Object
|
307
|
+
def random_get(store, args)
|
308
|
+
buf = args[0].value.to_i
|
309
|
+
buflen = args[1].value.to_i
|
310
|
+
randoms = SecureRandom.random_bytes(buflen) #: String
|
311
|
+
memory = store.memories[0]
|
312
|
+
memory.data[buf...(buf+buflen)] = randoms
|
313
|
+
0
|
53
314
|
end
|
54
315
|
|
55
316
|
private
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
|
3
|
+
module Wardite
|
4
|
+
# @rbs!
|
5
|
+
# interface _WasmCallable
|
6
|
+
# def call: (Store, Array[wasmValue]) -> wasmFuncReturn
|
7
|
+
# def []: (Store, Array[wasmValue]) -> wasmFuncReturn
|
8
|
+
# end
|
9
|
+
|
10
|
+
# @rbs!
|
11
|
+
# type wasmModuleSrc = Hash[Symbol, _WasmCallable] | WasmModule | HashModule
|
12
|
+
# type wasmModule = WasmModule | HashModule
|
13
|
+
|
14
|
+
module WasmModule
|
15
|
+
# @rbs fnname: Symbol
|
16
|
+
# @rbs store: Store
|
17
|
+
# @rbs args: Array[wasmValue]
|
18
|
+
# @rbs return: wasmFuncReturn
|
19
|
+
def invoke(fnname, store, *args)
|
20
|
+
self.__send__(fnname, store, args)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @rbs fnname: Symbol
|
24
|
+
# @rbs return: _WasmCallable
|
25
|
+
def callable(fnname)
|
26
|
+
self.method(fnname)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class HashModule
|
31
|
+
attr_accessor :hash #: Hash[Symbol, _WasmCallable]
|
32
|
+
|
33
|
+
# @rbs ha: Hash[Symbol, _WasmCallable]
|
34
|
+
def initialize(hash)
|
35
|
+
@hash = hash
|
36
|
+
end
|
37
|
+
|
38
|
+
# @rbs fnname: Symbol
|
39
|
+
# @rbs store: Store
|
40
|
+
# @rbs args: Array[wasmValue]
|
41
|
+
# @rbs return: wasmFuncReturn
|
42
|
+
def invoke(fnname, store, *args)
|
43
|
+
fn = self.hash[fnname.to_sym]
|
44
|
+
fn.call(store, args)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @rbs fnname: Symbol
|
48
|
+
# @rbs return: _WasmCallable
|
49
|
+
def callable(fnname)
|
50
|
+
self.hash[fnname.to_sym]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/wardite.rb
CHANGED
@@ -20,8 +20,6 @@ require_relative "wardite/alu_f32.generated"
|
|
20
20
|
require_relative "wardite/alu_f64.generated"
|
21
21
|
require_relative "wardite/convert.generated"
|
22
22
|
|
23
|
-
require_relative "wardite/wasi"
|
24
|
-
|
25
23
|
require "stringio"
|
26
24
|
|
27
25
|
module Wardite
|
@@ -38,13 +36,23 @@ module Wardite
|
|
38
36
|
|
39
37
|
attr_accessor :exports #: Exports
|
40
38
|
|
41
|
-
attr_reader :import_object #: Hash[Symbol,
|
39
|
+
attr_reader :import_object #: Hash[Symbol, wasmModule]
|
40
|
+
|
41
|
+
attr_accessor :wasi #: WasiSnapshotPreview1?
|
42
42
|
|
43
|
-
# @rbs import_object: Hash[Symbol,
|
43
|
+
# @rbs import_object: Hash[Symbol, wasmModuleSrc]
|
44
44
|
# @rbs &blk: (Instance) -> void
|
45
45
|
def initialize(import_object, &blk)
|
46
|
+
@wasi = nil
|
47
|
+
|
46
48
|
blk.call(self)
|
47
|
-
|
49
|
+
import_object.each_pair do |k, v|
|
50
|
+
if v.is_a?(Hash)
|
51
|
+
import_object[k] = HashModule.new(v)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
@import_object = import_object #: Hash[Symbol, wasmModule]
|
48
56
|
|
49
57
|
@store = Store.new(self)
|
50
58
|
@exports = Exports.new(self.export_section, store)
|
@@ -281,7 +289,8 @@ module Wardite
|
|
281
289
|
|
282
290
|
case fn
|
283
291
|
when WasmFunction
|
284
|
-
invoke_internal(fn)
|
292
|
+
r = invoke_internal(fn)
|
293
|
+
r
|
285
294
|
when ExternalFunction
|
286
295
|
invoke_external(fn)
|
287
296
|
else
|
@@ -313,25 +322,7 @@ module Wardite
|
|
313
322
|
raise LoadError, "stack too short"
|
314
323
|
end
|
315
324
|
self.stack = drained_stack(local_start)
|
316
|
-
|
317
|
-
wasm_function.locals_count.each_with_index do |count, i|
|
318
|
-
typ = wasm_function.locals_type[i]
|
319
|
-
count.times do
|
320
|
-
case typ
|
321
|
-
when :i32, :u32
|
322
|
-
locals.push I32(0)
|
323
|
-
when :i64, :u64
|
324
|
-
locals.push I64(0)
|
325
|
-
when :f32
|
326
|
-
locals.push F32(0.0)
|
327
|
-
when :f64
|
328
|
-
locals.push F64(0.0)
|
329
|
-
else
|
330
|
-
$stderr.puts "warning: unknown type #{typ.inspect}. default to I32"
|
331
|
-
locals.push I32(0)
|
332
|
-
end
|
333
|
-
end
|
334
|
-
end
|
325
|
+
locals.concat(wasm_function.default_locals)
|
335
326
|
|
336
327
|
arity = wasm_function.retsig.size
|
337
328
|
frame = Frame.new(-1, stack.size, wasm_function.body, arity, locals)
|
@@ -888,7 +879,7 @@ module Wardite
|
|
888
879
|
class Store
|
889
880
|
attr_accessor :funcs #: Array[WasmFunction|ExternalFunction]
|
890
881
|
|
891
|
-
|
882
|
+
attr_accessor :modules #: Hash[Symbol, wasmModule]
|
892
883
|
|
893
884
|
attr_accessor :memories #: Array[Memory]
|
894
885
|
|
@@ -907,21 +898,19 @@ module Wardite
|
|
907
898
|
|
908
899
|
import_section = inst.import_section
|
909
900
|
@funcs = []
|
901
|
+
@modules = inst.import_object
|
910
902
|
|
911
903
|
if type_section && func_section && code_section
|
912
904
|
import_section.imports.each do |desc|
|
913
905
|
callsig = type_section.defined_types[desc.sig_index]
|
914
906
|
retsig = type_section.defined_results[desc.sig_index]
|
915
|
-
|
916
|
-
if
|
907
|
+
target_module = self.modules[desc.module_name.to_sym]
|
908
|
+
if target_module.nil?
|
917
909
|
raise ::NameError, "module #{desc.module_name} not found"
|
918
910
|
end
|
919
|
-
|
920
|
-
if !imported_proc
|
921
|
-
raise ::NameError, "function #{desc.module_name}.#{desc.name} not found"
|
922
|
-
end
|
911
|
+
target_name = desc.name.to_sym
|
923
912
|
|
924
|
-
ext_function = ExternalFunction.new(callsig, retsig
|
913
|
+
ext_function = ExternalFunction.new(target_module, target_name, callsig, retsig)
|
925
914
|
self.funcs << ext_function
|
926
915
|
end
|
927
916
|
|
@@ -1213,7 +1202,10 @@ module Wardite
|
|
1213
1202
|
end
|
1214
1203
|
|
1215
1204
|
# TODO: common interface btw. WasmFunction and ExternalFunction?
|
1205
|
+
# may be _WasmCallable?
|
1216
1206
|
class WasmFunction
|
1207
|
+
include ValueHelper
|
1208
|
+
|
1217
1209
|
attr_accessor :callsig #: Array[Symbol]
|
1218
1210
|
|
1219
1211
|
attr_accessor :retsig #: Array[Symbol]
|
@@ -1222,6 +1214,8 @@ module Wardite
|
|
1222
1214
|
|
1223
1215
|
attr_accessor :findex #: Integer
|
1224
1216
|
|
1217
|
+
attr_accessor :default_locals #: Array[wasmValue]
|
1218
|
+
|
1225
1219
|
# @rbs callsig: Array[Symbol]
|
1226
1220
|
# @rbs retsig: Array[Symbol]
|
1227
1221
|
# @rbs code_body: CodeSection::CodeBody
|
@@ -1232,6 +1226,7 @@ module Wardite
|
|
1232
1226
|
|
1233
1227
|
@code_body = code_body
|
1234
1228
|
@findex = 0 # for debug
|
1229
|
+
@default_locals = construct_default_locals
|
1235
1230
|
end
|
1236
1231
|
|
1237
1232
|
# @rbs return: Array[Op]
|
@@ -1249,6 +1244,30 @@ module Wardite
|
|
1249
1244
|
code_body.locals_count
|
1250
1245
|
end
|
1251
1246
|
|
1247
|
+
# @rbs return: Array[wasmValue]
|
1248
|
+
def construct_default_locals
|
1249
|
+
locals = [] #: Array[wasmValue]
|
1250
|
+
locals_count.each_with_index do |count, i|
|
1251
|
+
typ = locals_type[i]
|
1252
|
+
count.times do
|
1253
|
+
case typ
|
1254
|
+
when :i32, :u32
|
1255
|
+
locals.push I32(0)
|
1256
|
+
when :i64, :u64
|
1257
|
+
locals.push I64(0)
|
1258
|
+
when :f32
|
1259
|
+
locals.push F32(0.0)
|
1260
|
+
when :f64
|
1261
|
+
locals.push F64(0.0)
|
1262
|
+
else
|
1263
|
+
$stderr.puts "warning: unknown type #{typ.inspect}. default to I32"
|
1264
|
+
locals.push I32(0)
|
1265
|
+
end
|
1266
|
+
end
|
1267
|
+
end
|
1268
|
+
locals
|
1269
|
+
end
|
1270
|
+
|
1252
1271
|
# @rbs override_type: Type?
|
1253
1272
|
# @rbs return: WasmFunction
|
1254
1273
|
def clone(override_type: nil)
|
@@ -1263,23 +1282,32 @@ module Wardite
|
|
1263
1282
|
|
1264
1283
|
# @rbs!
|
1265
1284
|
# type wasmFuncReturn = Object|nil
|
1266
|
-
# type wasmCallable = ^(Store, Array[wasmValue]) -> wasmFuncReturn
|
1267
1285
|
|
1268
1286
|
class ExternalFunction
|
1287
|
+
attr_accessor :target_module #: wasmModule
|
1288
|
+
|
1289
|
+
attr_accessor :name #: Symbol
|
1290
|
+
|
1269
1291
|
attr_accessor :callsig #: Array[Symbol]
|
1270
1292
|
|
1271
1293
|
attr_accessor :retsig #: Array[Symbol]
|
1272
1294
|
|
1273
|
-
attr_accessor :callable #:
|
1295
|
+
#attr_accessor :callable #: _WasmCallable
|
1274
1296
|
|
1275
1297
|
# @rbs callsig: Array[Symbol]
|
1276
1298
|
# @rbs retsig: Array[Symbol]
|
1277
|
-
# @rbs callable:
|
1299
|
+
# @rbs callable: _WasmCallable
|
1278
1300
|
# @rbs return: void
|
1279
|
-
def initialize(callsig, retsig
|
1301
|
+
def initialize(target_module, name, callsig, retsig)
|
1302
|
+
@target_module = target_module
|
1303
|
+
@name = name
|
1280
1304
|
@callsig = callsig
|
1281
1305
|
@retsig = retsig
|
1282
|
-
|
1306
|
+
end
|
1307
|
+
|
1308
|
+
# @rbs return: _WasmCallable
|
1309
|
+
def callable()
|
1310
|
+
target_module.callable(self.name)
|
1283
1311
|
end
|
1284
1312
|
|
1285
1313
|
# @rbs override_type: Type?
|
@@ -1287,9 +1315,9 @@ module Wardite
|
|
1287
1315
|
def clone(override_type: nil)
|
1288
1316
|
if override_type
|
1289
1317
|
# callable is assumed to be frozen, so we can copy its ref
|
1290
|
-
ExternalFunction.new(override_type.callsig, override_type.retsig
|
1318
|
+
ExternalFunction.new(target_module, name, override_type.callsig, override_type.retsig)
|
1291
1319
|
else
|
1292
|
-
ExternalFunction.new(callsig, retsig
|
1320
|
+
ExternalFunction.new(target_module, name, callsig, retsig)
|
1293
1321
|
end
|
1294
1322
|
end
|
1295
1323
|
end
|
data/misc/bench-value.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "benchmark"
|
2
|
+
require "wardite"
|
3
|
+
|
4
|
+
N = 1000000
|
5
|
+
|
6
|
+
i32_100 = Wardite::I32.new(100)
|
7
|
+
i32_200 = Wardite::I32.new(200)
|
8
|
+
$RES = {}
|
9
|
+
$RES2 = {}
|
10
|
+
|
11
|
+
Benchmark.bmbm do |x|
|
12
|
+
x.report("add via value") do
|
13
|
+
N.times do |i|
|
14
|
+
res = Wardite::I32.new(i32_100.value + i32_200.value)
|
15
|
+
$RES[i%10] = res # avoid optimization
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
x.report("add immediate") do
|
20
|
+
N.times do |i|
|
21
|
+
res = 100 + 200
|
22
|
+
$RES2[i%10] = res
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/misc/slides/fib.c
ADDED
Binary file
|
Binary file
|
Binary file
|