wardite 0.1.2 → 0.2.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/Rakefile +178 -0
- data/Steepfile +1 -0
- data/examples/consts.wat +12 -0
- data/lib/wardite/alu_f32.generated.rb +250 -0
- data/lib/wardite/alu_f64.generated.rb +250 -0
- data/lib/wardite/alu_i32.generated.rb +457 -0
- data/lib/wardite/alu_i64.generated.rb +514 -0
- data/lib/wardite/convert.generated.rb +234 -0
- data/lib/wardite/instruction.rb +82 -33
- data/lib/wardite/leb128.rb +1 -1
- data/lib/wardite/value.rb +627 -0
- data/lib/wardite/version.rb +1 -1
- data/lib/wardite/wasi.rb +6 -4
- data/lib/wardite.rb +192 -115
- data/scripts/gen_alu.rb +750 -0
- data/scripts/gen_conv.rb +76 -0
- data/scripts/templates/alu_module.rb.tmpl +18 -0
- data/scripts/templates/conv_module.rb.tmpl +18 -0
- data/sig/generated/wardite/alu_f32.generated.rbs +11 -0
- data/sig/generated/wardite/alu_f64.generated.rbs +11 -0
- data/sig/generated/wardite/alu_i32.generated.rbs +11 -0
- data/sig/generated/wardite/alu_i64.generated.rbs +11 -0
- data/sig/generated/wardite/convert.generated.rbs +11 -0
- data/sig/generated/wardite/instruction.rbs +15 -6
- data/sig/generated/wardite/leb128.rbs +1 -1
- data/sig/generated/wardite/value.rbs +302 -0
- data/sig/generated/wardite/wasi.rbs +4 -2
- data/sig/generated/wardite.rbs +27 -12
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cefed459056cdf59c5c8823b1b4ef8ff53c84fd09a9f73883aaa291561ba4e00
|
4
|
+
data.tar.gz: b4ac97c31de3cc655aaf68d9c2097d1cb73ff67a184fd0c365d99b36371f1f93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3987aab13095263b109e7c907bee2640c3b9d2a5777b1b81812f692508de160d7fdd9f28e8c19c25d53445905e3b7b65379e0443f36dd56232e5c61b7d054bc
|
7
|
+
data.tar.gz: ca3e1e1b0390869ce69ddc880e574ff3fb6c75c7def7538ad628c121ea5c12e1c860dbadc960cbaba48841f6ab5be3f1eeb117e0822dd9488271eab0eb1745d9
|
data/Rakefile
CHANGED
@@ -15,5 +15,183 @@ task :check do
|
|
15
15
|
sh "bundle exec steep check"
|
16
16
|
end
|
17
17
|
|
18
|
+
desc "Compile wat"
|
19
|
+
task :wasm, [:name] do |t, args|
|
20
|
+
Dir.chdir "examples" do
|
21
|
+
sh "wat2wasm #{args.name}.wat"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Generate codes"
|
26
|
+
task :generate do
|
27
|
+
require_relative "scripts/gen_alu"
|
28
|
+
require_relative "scripts/gen_conv"
|
29
|
+
libdir = File.expand_path("../lib", __FILE__)
|
30
|
+
|
31
|
+
GenAlu.execute(libdir + "/wardite/alu_i32.generated.rb", prefix: "i32", defined_ops: [
|
32
|
+
:load,
|
33
|
+
:load8_s,
|
34
|
+
:load8_u,
|
35
|
+
:load16_s,
|
36
|
+
:load16_u,
|
37
|
+
:store,
|
38
|
+
:store8,
|
39
|
+
:store16,
|
40
|
+
:const,
|
41
|
+
:eqz,
|
42
|
+
:eq,
|
43
|
+
:ne,
|
44
|
+
:lts,
|
45
|
+
:ltu,
|
46
|
+
:gts,
|
47
|
+
:gtu,
|
48
|
+
:les,
|
49
|
+
:leu,
|
50
|
+
:ges,
|
51
|
+
:geu,
|
52
|
+
:clz,
|
53
|
+
:ctz,
|
54
|
+
:popcnt,
|
55
|
+
:add,
|
56
|
+
:sub,
|
57
|
+
:mul,
|
58
|
+
:div_s,
|
59
|
+
:div_u,
|
60
|
+
:rem_s,
|
61
|
+
:rem_u,
|
62
|
+
:and,
|
63
|
+
:or,
|
64
|
+
:xor,
|
65
|
+
:shl,
|
66
|
+
:shr_s,
|
67
|
+
:shr_u,
|
68
|
+
:rotl,
|
69
|
+
:rotr,
|
70
|
+
])
|
71
|
+
GenAlu.execute(libdir + "/wardite/alu_i64.generated.rb", prefix: "i64", defined_ops: [
|
72
|
+
:load,
|
73
|
+
:load8_s,
|
74
|
+
:load8_u,
|
75
|
+
:load16_s,
|
76
|
+
:load16_u,
|
77
|
+
:load32_s,
|
78
|
+
:load32_u,
|
79
|
+
:store,
|
80
|
+
:store8,
|
81
|
+
:store16,
|
82
|
+
:store32,
|
83
|
+
:const,
|
84
|
+
:eqz,
|
85
|
+
:eq,
|
86
|
+
:ne,
|
87
|
+
:lts,
|
88
|
+
:ltu,
|
89
|
+
:gts,
|
90
|
+
:gtu,
|
91
|
+
:les,
|
92
|
+
:leu,
|
93
|
+
:ges,
|
94
|
+
:geu,
|
95
|
+
:clz,
|
96
|
+
:ctz,
|
97
|
+
:popcnt,
|
98
|
+
:add,
|
99
|
+
:sub,
|
100
|
+
:mul,
|
101
|
+
:div_s,
|
102
|
+
:div_u,
|
103
|
+
:rem_s,
|
104
|
+
:rem_u,
|
105
|
+
:and,
|
106
|
+
:or,
|
107
|
+
:xor,
|
108
|
+
:shl,
|
109
|
+
:shr_s,
|
110
|
+
:shr_u,
|
111
|
+
:rotl,
|
112
|
+
:rotr,
|
113
|
+
])
|
114
|
+
GenAlu.execute(libdir + "/wardite/alu_f32.generated.rb", prefix: "f32", defined_ops: [
|
115
|
+
:load,
|
116
|
+
:store,
|
117
|
+
:const__f,
|
118
|
+
:eqz,
|
119
|
+
:eq,
|
120
|
+
:ne,
|
121
|
+
:lt,
|
122
|
+
:gt,
|
123
|
+
:le,
|
124
|
+
:ge,
|
125
|
+
:abs,
|
126
|
+
:neg,
|
127
|
+
:ceil,
|
128
|
+
:floor,
|
129
|
+
:trunc,
|
130
|
+
:nearest,
|
131
|
+
:sqrt,
|
132
|
+
:add,
|
133
|
+
:sub,
|
134
|
+
:mul,
|
135
|
+
:div,
|
136
|
+
:min,
|
137
|
+
:max,
|
138
|
+
:copysign,
|
139
|
+
])
|
140
|
+
GenAlu.execute(libdir + "/wardite/alu_f64.generated.rb", prefix: "f64", defined_ops: [
|
141
|
+
:load,
|
142
|
+
:store,
|
143
|
+
:const__f,
|
144
|
+
:eqz,
|
145
|
+
:eq,
|
146
|
+
:ne,
|
147
|
+
:lt,
|
148
|
+
:gt,
|
149
|
+
:le,
|
150
|
+
:ge,
|
151
|
+
:abs,
|
152
|
+
:neg,
|
153
|
+
:ceil,
|
154
|
+
:floor,
|
155
|
+
:trunc,
|
156
|
+
:nearest,
|
157
|
+
:sqrt,
|
158
|
+
:add,
|
159
|
+
:sub,
|
160
|
+
:mul,
|
161
|
+
:div,
|
162
|
+
:min,
|
163
|
+
:max,
|
164
|
+
:copysign,
|
165
|
+
])
|
166
|
+
|
167
|
+
GenConv.execute(libdir + "/wardite/convert.generated.rb", defined_ops: {
|
168
|
+
i32: {
|
169
|
+
wrap: [:i64],
|
170
|
+
trunc_s: [:f32, :f64],
|
171
|
+
trunc_u: [:f32, :f64],
|
172
|
+
reinterpret: [:f32],
|
173
|
+
},
|
174
|
+
i64: {
|
175
|
+
extend_s: [:i32, :i64],
|
176
|
+
extend_u: [:i32, :i64],
|
177
|
+
trunc_s: [:f32, :f64],
|
178
|
+
trunc_u: [:f32, :f64],
|
179
|
+
reinterpret: [:f64],
|
180
|
+
},
|
181
|
+
f32: {
|
182
|
+
convert_s: [:i32, :i64],
|
183
|
+
convert_u: [:i32, :i64],
|
184
|
+
demote: [:f64],
|
185
|
+
reinterpret: [:i32],
|
186
|
+
},
|
187
|
+
f64: {
|
188
|
+
convert_s: [:i32, :i64],
|
189
|
+
convert_u: [:i32, :i64],
|
190
|
+
promote: [:f32],
|
191
|
+
reinterpret: [:i64],
|
192
|
+
},
|
193
|
+
})
|
194
|
+
end
|
195
|
+
|
18
196
|
task default: %i[test check]
|
19
197
|
|
data/Steepfile
CHANGED
data/examples/consts.wat
ADDED
@@ -0,0 +1,250 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
require_relative "value"
|
3
|
+
|
4
|
+
module Wardite
|
5
|
+
module Evaluator
|
6
|
+
# @rbs runtime: Runtime
|
7
|
+
# @rbs frame: Frame
|
8
|
+
# @rbs insn: Op
|
9
|
+
# @rbs return: void
|
10
|
+
def self.f32_eval_insn(runtime, frame, insn)
|
11
|
+
case insn.code
|
12
|
+
|
13
|
+
when :f32_load
|
14
|
+
_align = insn.operand[0] # TODO: alignment support?
|
15
|
+
offset = insn.operand[1]
|
16
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
17
|
+
|
18
|
+
addr = runtime.stack.pop
|
19
|
+
if !addr.is_a?(I32)
|
20
|
+
raise EvalError, "maybe stack too short"
|
21
|
+
end
|
22
|
+
|
23
|
+
at = addr.value + offset
|
24
|
+
data_end = at + F32.new.memsize / 8
|
25
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
26
|
+
buf = memory.data[at...data_end]
|
27
|
+
if !buf
|
28
|
+
raise EvalError, "invalid memory range"
|
29
|
+
end
|
30
|
+
runtime.stack.push(F32.from_bytes(buf))
|
31
|
+
|
32
|
+
|
33
|
+
when :f32_store
|
34
|
+
_align = insn.operand[0] # TODO: alignment support?
|
35
|
+
offset = insn.operand[1]
|
36
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
37
|
+
|
38
|
+
value = runtime.stack.pop
|
39
|
+
addr = runtime.stack.pop
|
40
|
+
if !value.is_a?(F32) || !addr.is_a?(I32)
|
41
|
+
raise EvalError, "maybe stack too short"
|
42
|
+
end
|
43
|
+
|
44
|
+
at = addr.value + offset
|
45
|
+
data_end = at + value.packed.size
|
46
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
47
|
+
memory.data[at...data_end] = value.packed
|
48
|
+
|
49
|
+
|
50
|
+
when :f32_const
|
51
|
+
const = insn.operand[0]
|
52
|
+
if !const.is_a?(Float)
|
53
|
+
raise EvalError, "invalid type of operand"
|
54
|
+
end
|
55
|
+
runtime.stack.push(F32(const))
|
56
|
+
|
57
|
+
|
58
|
+
when :f32_eqz
|
59
|
+
target = runtime.stack.pop
|
60
|
+
if !target.is_a?(F32)
|
61
|
+
raise EvalError, "maybe empty or invalid stack"
|
62
|
+
end
|
63
|
+
value = target.value.zero? ? 1 : 0
|
64
|
+
runtime.stack.push(I32(value))
|
65
|
+
|
66
|
+
|
67
|
+
when :f32_eq
|
68
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
69
|
+
if !right.is_a?(F32) || !left.is_a?(F32)
|
70
|
+
raise EvalError, "maybe empty or invalid stack"
|
71
|
+
end
|
72
|
+
value = (left.value == right.value) ? 1 : 0
|
73
|
+
runtime.stack.push(I32(value))
|
74
|
+
|
75
|
+
|
76
|
+
when :f32_ne
|
77
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
78
|
+
if !right.is_a?(F32) || !left.is_a?(F32)
|
79
|
+
raise EvalError, "maybe empty or invalid stack"
|
80
|
+
end
|
81
|
+
value = (left.value != right.value) ? 1 : 0
|
82
|
+
runtime.stack.push(I32(value))
|
83
|
+
|
84
|
+
|
85
|
+
when :f32_lt
|
86
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
87
|
+
if !right.is_a?(F32) || !left.is_a?(F32)
|
88
|
+
raise EvalError, "maybe empty or invalid stack"
|
89
|
+
end
|
90
|
+
value = (left.value < right.value) ? 1 : 0
|
91
|
+
runtime.stack.push(I32(value))
|
92
|
+
|
93
|
+
|
94
|
+
when :f32_gt
|
95
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
96
|
+
if !right.is_a?(F32) || !left.is_a?(F32)
|
97
|
+
raise EvalError, "maybe empty or invalid stack"
|
98
|
+
end
|
99
|
+
value = (left.value > right.value) ? 1 : 0
|
100
|
+
runtime.stack.push(I32(value))
|
101
|
+
|
102
|
+
|
103
|
+
when :f32_le
|
104
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
105
|
+
if !right.is_a?(F32) || !left.is_a?(F32)
|
106
|
+
raise EvalError, "maybe empty or invalid stack"
|
107
|
+
end
|
108
|
+
value = (left.value <= right.value) ? 1 : 0
|
109
|
+
runtime.stack.push(I32(value))
|
110
|
+
|
111
|
+
|
112
|
+
when :f32_ge
|
113
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
114
|
+
if !right.is_a?(F32) || !left.is_a?(F32)
|
115
|
+
raise EvalError, "maybe empty or invalid stack"
|
116
|
+
end
|
117
|
+
value = (left.value >= right.value) ? 1 : 0
|
118
|
+
runtime.stack.push(I32(value))
|
119
|
+
|
120
|
+
|
121
|
+
when :f32_abs
|
122
|
+
x = runtime.stack.pop
|
123
|
+
if !x.is_a?(F32)
|
124
|
+
raise EvalError, "maybe empty or invalid stack"
|
125
|
+
end
|
126
|
+
runtime.stack.push(F32(x.value.abs))
|
127
|
+
|
128
|
+
|
129
|
+
when :f32_neg
|
130
|
+
x = runtime.stack.pop
|
131
|
+
if !x.is_a?(F32)
|
132
|
+
raise EvalError, "maybe empty or invalid stack"
|
133
|
+
end
|
134
|
+
runtime.stack.push(F32(-(x.value)))
|
135
|
+
|
136
|
+
|
137
|
+
when :f32_ceil
|
138
|
+
x = runtime.stack.pop
|
139
|
+
if !x.is_a?(F32)
|
140
|
+
raise EvalError, "maybe empty or invalid stack"
|
141
|
+
end
|
142
|
+
runtime.stack.push(F32(x.value.ceil.to_f))
|
143
|
+
|
144
|
+
|
145
|
+
when :f32_floor
|
146
|
+
x = runtime.stack.pop
|
147
|
+
if !x.is_a?(F32)
|
148
|
+
raise EvalError, "maybe empty or invalid stack"
|
149
|
+
end
|
150
|
+
runtime.stack.push(F32(x.value.floor.to_f))
|
151
|
+
|
152
|
+
|
153
|
+
when :f32_trunc
|
154
|
+
x = runtime.stack.pop
|
155
|
+
if !x.is_a?(F32)
|
156
|
+
raise EvalError, "maybe empty or invalid stack"
|
157
|
+
end
|
158
|
+
runtime.stack.push(F32(x.value.to_i.to_f))
|
159
|
+
|
160
|
+
|
161
|
+
when :f32_nearest
|
162
|
+
x = runtime.stack.pop
|
163
|
+
if !x.is_a?(F32)
|
164
|
+
raise EvalError, "maybe empty or invalid stack"
|
165
|
+
end
|
166
|
+
runtime.stack.push(F32(x.value.round.to_f))
|
167
|
+
|
168
|
+
|
169
|
+
when :f32_sqrt
|
170
|
+
x = runtime.stack.pop
|
171
|
+
if !x.is_a?(F32)
|
172
|
+
raise EvalError, "maybe empty or invalid stack"
|
173
|
+
end
|
174
|
+
runtime.stack.push(F32(x.value ** 0.5))
|
175
|
+
|
176
|
+
|
177
|
+
when :f32_add
|
178
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
179
|
+
if !right.is_a?(F32) || !left.is_a?(F32)
|
180
|
+
raise EvalError, "maybe empty or invalid stack"
|
181
|
+
end
|
182
|
+
runtime.stack.push(F32(left.value + right.value))
|
183
|
+
|
184
|
+
|
185
|
+
when :f32_sub
|
186
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
187
|
+
if !right.is_a?(F32) || !left.is_a?(F32)
|
188
|
+
raise EvalError, "maybe empty or invalid stack"
|
189
|
+
end
|
190
|
+
runtime.stack.push(F32(left.value - right.value))
|
191
|
+
|
192
|
+
|
193
|
+
when :f32_mul
|
194
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
195
|
+
if !right.is_a?(F32) || !left.is_a?(F32)
|
196
|
+
raise EvalError, "maybe empty or invalid stack"
|
197
|
+
end
|
198
|
+
runtime.stack.push(F32(left.value * right.value))
|
199
|
+
|
200
|
+
|
201
|
+
when :f32_div
|
202
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
203
|
+
if !right.is_a?(F32) || !left.is_a?(F32)
|
204
|
+
raise EvalError, "maybe empty or invalid stack"
|
205
|
+
end
|
206
|
+
runtime.stack.push(F32(left.value / right.value))
|
207
|
+
|
208
|
+
|
209
|
+
when :f32_min
|
210
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
211
|
+
if !right.is_a?(F32) || !left.is_a?(F32)
|
212
|
+
raise EvalError, "maybe empty or invalid stack"
|
213
|
+
end
|
214
|
+
if right.value.nan? || left.value.nan?
|
215
|
+
runtime.stack.push(F32(Float::NAN))
|
216
|
+
return
|
217
|
+
end
|
218
|
+
runtime.stack.push(F32([left.value, right.value].min))
|
219
|
+
|
220
|
+
|
221
|
+
when :f32_max
|
222
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
223
|
+
if !right.is_a?(F32) || !left.is_a?(F32)
|
224
|
+
raise EvalError, "maybe empty or invalid stack"
|
225
|
+
end
|
226
|
+
if right.value.nan? || left.value.nan?
|
227
|
+
runtime.stack.push(F32(Float::NAN))
|
228
|
+
return
|
229
|
+
end
|
230
|
+
runtime.stack.push(F32([left.value, right.value].max))
|
231
|
+
|
232
|
+
|
233
|
+
when :f32_copysign
|
234
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
235
|
+
if !right.is_a?(F32) || !left.is_a?(F32)
|
236
|
+
raise EvalError, "maybe empty or invalid stack"
|
237
|
+
end
|
238
|
+
if left.sign == right.sign
|
239
|
+
runtime.stack.push(F32(left.value))
|
240
|
+
else
|
241
|
+
runtime.stack.push(F32(-left.value))
|
242
|
+
end
|
243
|
+
|
244
|
+
|
245
|
+
else
|
246
|
+
raise "Unknown opcode for namespace #{insn.namespace}: #{insn.code}"
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
@@ -0,0 +1,250 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
require_relative "value"
|
3
|
+
|
4
|
+
module Wardite
|
5
|
+
module Evaluator
|
6
|
+
# @rbs runtime: Runtime
|
7
|
+
# @rbs frame: Frame
|
8
|
+
# @rbs insn: Op
|
9
|
+
# @rbs return: void
|
10
|
+
def self.f64_eval_insn(runtime, frame, insn)
|
11
|
+
case insn.code
|
12
|
+
|
13
|
+
when :f64_load
|
14
|
+
_align = insn.operand[0] # TODO: alignment support?
|
15
|
+
offset = insn.operand[1]
|
16
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
17
|
+
|
18
|
+
addr = runtime.stack.pop
|
19
|
+
if !addr.is_a?(I32)
|
20
|
+
raise EvalError, "maybe stack too short"
|
21
|
+
end
|
22
|
+
|
23
|
+
at = addr.value + offset
|
24
|
+
data_end = at + F64.new.memsize / 8
|
25
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
26
|
+
buf = memory.data[at...data_end]
|
27
|
+
if !buf
|
28
|
+
raise EvalError, "invalid memory range"
|
29
|
+
end
|
30
|
+
runtime.stack.push(F64.from_bytes(buf))
|
31
|
+
|
32
|
+
|
33
|
+
when :f64_store
|
34
|
+
_align = insn.operand[0] # TODO: alignment support?
|
35
|
+
offset = insn.operand[1]
|
36
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
37
|
+
|
38
|
+
value = runtime.stack.pop
|
39
|
+
addr = runtime.stack.pop
|
40
|
+
if !value.is_a?(F64) || !addr.is_a?(I32)
|
41
|
+
raise EvalError, "maybe stack too short"
|
42
|
+
end
|
43
|
+
|
44
|
+
at = addr.value + offset
|
45
|
+
data_end = at + value.packed.size
|
46
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
47
|
+
memory.data[at...data_end] = value.packed
|
48
|
+
|
49
|
+
|
50
|
+
when :f64_const
|
51
|
+
const = insn.operand[0]
|
52
|
+
if !const.is_a?(Float)
|
53
|
+
raise EvalError, "invalid type of operand"
|
54
|
+
end
|
55
|
+
runtime.stack.push(F64(const))
|
56
|
+
|
57
|
+
|
58
|
+
when :f64_eqz
|
59
|
+
target = runtime.stack.pop
|
60
|
+
if !target.is_a?(F64)
|
61
|
+
raise EvalError, "maybe empty or invalid stack"
|
62
|
+
end
|
63
|
+
value = target.value.zero? ? 1 : 0
|
64
|
+
runtime.stack.push(I32(value))
|
65
|
+
|
66
|
+
|
67
|
+
when :f64_eq
|
68
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
69
|
+
if !right.is_a?(F64) || !left.is_a?(F64)
|
70
|
+
raise EvalError, "maybe empty or invalid stack"
|
71
|
+
end
|
72
|
+
value = (left.value == right.value) ? 1 : 0
|
73
|
+
runtime.stack.push(I32(value))
|
74
|
+
|
75
|
+
|
76
|
+
when :f64_ne
|
77
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
78
|
+
if !right.is_a?(F64) || !left.is_a?(F64)
|
79
|
+
raise EvalError, "maybe empty or invalid stack"
|
80
|
+
end
|
81
|
+
value = (left.value != right.value) ? 1 : 0
|
82
|
+
runtime.stack.push(I32(value))
|
83
|
+
|
84
|
+
|
85
|
+
when :f64_lt
|
86
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
87
|
+
if !right.is_a?(F64) || !left.is_a?(F64)
|
88
|
+
raise EvalError, "maybe empty or invalid stack"
|
89
|
+
end
|
90
|
+
value = (left.value < right.value) ? 1 : 0
|
91
|
+
runtime.stack.push(I32(value))
|
92
|
+
|
93
|
+
|
94
|
+
when :f64_gt
|
95
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
96
|
+
if !right.is_a?(F64) || !left.is_a?(F64)
|
97
|
+
raise EvalError, "maybe empty or invalid stack"
|
98
|
+
end
|
99
|
+
value = (left.value > right.value) ? 1 : 0
|
100
|
+
runtime.stack.push(I32(value))
|
101
|
+
|
102
|
+
|
103
|
+
when :f64_le
|
104
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
105
|
+
if !right.is_a?(F64) || !left.is_a?(F64)
|
106
|
+
raise EvalError, "maybe empty or invalid stack"
|
107
|
+
end
|
108
|
+
value = (left.value <= right.value) ? 1 : 0
|
109
|
+
runtime.stack.push(I32(value))
|
110
|
+
|
111
|
+
|
112
|
+
when :f64_ge
|
113
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
114
|
+
if !right.is_a?(F64) || !left.is_a?(F64)
|
115
|
+
raise EvalError, "maybe empty or invalid stack"
|
116
|
+
end
|
117
|
+
value = (left.value >= right.value) ? 1 : 0
|
118
|
+
runtime.stack.push(I32(value))
|
119
|
+
|
120
|
+
|
121
|
+
when :f64_abs
|
122
|
+
x = runtime.stack.pop
|
123
|
+
if !x.is_a?(F64)
|
124
|
+
raise EvalError, "maybe empty or invalid stack"
|
125
|
+
end
|
126
|
+
runtime.stack.push(F64(x.value.abs))
|
127
|
+
|
128
|
+
|
129
|
+
when :f64_neg
|
130
|
+
x = runtime.stack.pop
|
131
|
+
if !x.is_a?(F64)
|
132
|
+
raise EvalError, "maybe empty or invalid stack"
|
133
|
+
end
|
134
|
+
runtime.stack.push(F64(-(x.value)))
|
135
|
+
|
136
|
+
|
137
|
+
when :f64_ceil
|
138
|
+
x = runtime.stack.pop
|
139
|
+
if !x.is_a?(F64)
|
140
|
+
raise EvalError, "maybe empty or invalid stack"
|
141
|
+
end
|
142
|
+
runtime.stack.push(F64(x.value.ceil.to_f))
|
143
|
+
|
144
|
+
|
145
|
+
when :f64_floor
|
146
|
+
x = runtime.stack.pop
|
147
|
+
if !x.is_a?(F64)
|
148
|
+
raise EvalError, "maybe empty or invalid stack"
|
149
|
+
end
|
150
|
+
runtime.stack.push(F64(x.value.floor.to_f))
|
151
|
+
|
152
|
+
|
153
|
+
when :f64_trunc
|
154
|
+
x = runtime.stack.pop
|
155
|
+
if !x.is_a?(F64)
|
156
|
+
raise EvalError, "maybe empty or invalid stack"
|
157
|
+
end
|
158
|
+
runtime.stack.push(F64(x.value.to_i.to_f))
|
159
|
+
|
160
|
+
|
161
|
+
when :f64_nearest
|
162
|
+
x = runtime.stack.pop
|
163
|
+
if !x.is_a?(F64)
|
164
|
+
raise EvalError, "maybe empty or invalid stack"
|
165
|
+
end
|
166
|
+
runtime.stack.push(F64(x.value.round.to_f))
|
167
|
+
|
168
|
+
|
169
|
+
when :f64_sqrt
|
170
|
+
x = runtime.stack.pop
|
171
|
+
if !x.is_a?(F64)
|
172
|
+
raise EvalError, "maybe empty or invalid stack"
|
173
|
+
end
|
174
|
+
runtime.stack.push(F64(x.value ** 0.5))
|
175
|
+
|
176
|
+
|
177
|
+
when :f64_add
|
178
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
179
|
+
if !right.is_a?(F64) || !left.is_a?(F64)
|
180
|
+
raise EvalError, "maybe empty or invalid stack"
|
181
|
+
end
|
182
|
+
runtime.stack.push(F64(left.value + right.value))
|
183
|
+
|
184
|
+
|
185
|
+
when :f64_sub
|
186
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
187
|
+
if !right.is_a?(F64) || !left.is_a?(F64)
|
188
|
+
raise EvalError, "maybe empty or invalid stack"
|
189
|
+
end
|
190
|
+
runtime.stack.push(F64(left.value - right.value))
|
191
|
+
|
192
|
+
|
193
|
+
when :f64_mul
|
194
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
195
|
+
if !right.is_a?(F64) || !left.is_a?(F64)
|
196
|
+
raise EvalError, "maybe empty or invalid stack"
|
197
|
+
end
|
198
|
+
runtime.stack.push(F64(left.value * right.value))
|
199
|
+
|
200
|
+
|
201
|
+
when :f64_div
|
202
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
203
|
+
if !right.is_a?(F64) || !left.is_a?(F64)
|
204
|
+
raise EvalError, "maybe empty or invalid stack"
|
205
|
+
end
|
206
|
+
runtime.stack.push(F64(left.value / right.value))
|
207
|
+
|
208
|
+
|
209
|
+
when :f64_min
|
210
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
211
|
+
if !right.is_a?(F64) || !left.is_a?(F64)
|
212
|
+
raise EvalError, "maybe empty or invalid stack"
|
213
|
+
end
|
214
|
+
if right.value.nan? || left.value.nan?
|
215
|
+
runtime.stack.push(F64(Float::NAN))
|
216
|
+
return
|
217
|
+
end
|
218
|
+
runtime.stack.push(F64([left.value, right.value].min))
|
219
|
+
|
220
|
+
|
221
|
+
when :f64_max
|
222
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
223
|
+
if !right.is_a?(F64) || !left.is_a?(F64)
|
224
|
+
raise EvalError, "maybe empty or invalid stack"
|
225
|
+
end
|
226
|
+
if right.value.nan? || left.value.nan?
|
227
|
+
runtime.stack.push(F64(Float::NAN))
|
228
|
+
return
|
229
|
+
end
|
230
|
+
runtime.stack.push(F64([left.value, right.value].max))
|
231
|
+
|
232
|
+
|
233
|
+
when :f64_copysign
|
234
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
235
|
+
if !right.is_a?(F64) || !left.is_a?(F64)
|
236
|
+
raise EvalError, "maybe empty or invalid stack"
|
237
|
+
end
|
238
|
+
if left.sign == right.sign
|
239
|
+
runtime.stack.push(F64(left.value))
|
240
|
+
else
|
241
|
+
runtime.stack.push(F64(-left.value))
|
242
|
+
end
|
243
|
+
|
244
|
+
|
245
|
+
else
|
246
|
+
raise "Unknown opcode for namespace #{insn.namespace}: #{insn.code}"
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|