WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

UvmInterpreterSpec.scala 48.1 KB
Newer Older
Kunshan Wang's avatar
Kunshan Wang committed
1
2
3
4
5
6
7
8
9
package uvm.refimpl.itpr

import org.scalatest._
import java.io.FileReader
import uvm._
import uvm.types._
import uvm.ssavariables._
import uvm.refimpl._
import uvm.refimpl.itpr._
10
import uvm.refimpl.mem._
Kunshan Wang's avatar
Kunshan Wang committed
11
12
13
import MemoryOrder._
import AtomicRMWOptr._
import uvm.refimpl.mem.TypeSizes.Word
Kunshan Wang's avatar
Kunshan Wang committed
14
15
import uvm.refimpl.TrapHandlerResult.{ ThreadExit, Rebind }
import uvm.refimpl.HowToResume.{ PassValues, ThrowExc }
Kunshan Wang's avatar
Kunshan Wang committed
16

17
import ch.qos.logback.classic.Level._
Kunshan Wang's avatar
Kunshan Wang committed
18

19
class UvmInterpreterSpec extends UvmBundleTesterBase {
Kunshan Wang's avatar
Kunshan Wang committed
20

21
22
  setLogLevels(
    ROOT_LOGGER_NAME -> INFO,
Kunshan Wang's avatar
Kunshan Wang committed
23
    //"uvm.refimpl.mem.simpleimmix.SimpleImmixCollector$" -> DEBUG,
24
    "uvm.refimpl.itpr" -> DEBUG)
Kunshan Wang's avatar
Kunshan Wang committed
25

Kunshan Wang's avatar
Kunshan Wang committed
26
  override def makeMicroVM = new MicroVM(heapSize = 8L * 1024L * 1024L)
27

Kunshan Wang's avatar
Kunshan Wang committed
28
29
  preloadBundles("tests/uvm-refimpl-test/primitives.uir",
    "tests/uvm-refimpl-test/basic-tests.uir")
30

31
32
  "The constant pool" should "contain appropriate constant values" in {
    def gvb(name: String) = microVM.constantPool.getGlobalVarBox(microVM.globalBundle.globalVarNs(name))
33

34
35
    gvb("@TRUE").asUInt(1) shouldBe 1
    gvb("@FALSE").asUInt(1) shouldBe 0
36

37
38
39
    gvb("@I32_1").asUInt(32) shouldBe 1
    gvb("@I32_2").asUInt(32) shouldBe 2
    gvb("@I32_7").asUInt(32) shouldBe 7
40

41
42
    gvb("@I64_5").asUInt(64) shouldBe 5
  }
Kunshan Wang's avatar
Kunshan Wang committed
43
44

  "Binary operations" should "work on int<32>" in {
Kunshan Wang's avatar
Kunshan Wang committed
45
    val ctx = microVM.newContext()
Kunshan Wang's avatar
Kunshan Wang committed
46

Kunshan Wang's avatar
Kunshan Wang committed
47
48
49
    val func = ctx.func("@binops32")
    val arg0 = ctx.i32(42)
    val arg1 = ctx.i32(3)
Kunshan Wang's avatar
Kunshan Wang committed
50

Kunshan Wang's avatar
Kunshan Wang committed
51
52
    testFunc(ctx, func, Seq(arg0, arg1)) { (ctx, th, st, wp) =>
      val Seq(add, sub, mul, udiv, sdiv, urem, srem, shl, lshr, ashr, and, or, xor) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

      add.vb.asSInt(32) shouldEqual 45
      sub.vb.asSInt(32) shouldEqual 39
      mul.vb.asSInt(32) shouldEqual 126
      udiv.vb.asUInt(32) shouldEqual 14
      sdiv.vb.asSInt(32) shouldEqual 14
      urem.vb.asUInt(32) shouldEqual 0
      srem.vb.asSInt(32) shouldEqual 0
      shl.vb.asSInt(32) shouldEqual 336
      lshr.vb.asUInt(32) shouldEqual 5
      ashr.vb.asSInt(32) shouldEqual 5
      and.vb.asSInt(32) shouldEqual 2
      or.vb.asSInt(32) shouldEqual 43
      xor.vb.asSInt(32) shouldEqual 41

Kunshan Wang's avatar
Kunshan Wang committed
68
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
69
70
    }

Kunshan Wang's avatar
Kunshan Wang committed
71
72
    val arg2 = ctx.handleFromInt(-100, 32)
    val arg3 = ctx.handleFromInt(6, 32)
Kunshan Wang's avatar
Kunshan Wang committed
73

Kunshan Wang's avatar
Kunshan Wang committed
74
75
    testFunc(ctx, func, Seq(arg2, arg3)) { (ctx, th, st, wp) =>
      val Seq(add, sub, mul, udiv, sdiv, urem, srem, shl, lshr, ashr, and, or, xor) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
76
77
78
79
80
      sdiv.vb.asSInt(32) shouldEqual -16
      srem.vb.asSInt(32) shouldEqual -4
      lshr.vb.asUInt(32) shouldEqual 67108862
      ashr.vb.asSInt(32) shouldEqual -2

Kunshan Wang's avatar
Kunshan Wang committed
81
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
82
83
    }

Kunshan Wang's avatar
Kunshan Wang committed
84
85
    val arg4 = ctx.handleFromInt(42, 32)
    val arg5 = ctx.handleFromInt(-15, 32)
Kunshan Wang's avatar
Kunshan Wang committed
86

Kunshan Wang's avatar
Kunshan Wang committed
87
88
    testFunc(ctx, func, Seq(arg4, arg5)) { (ctx, th, st, wp) =>
      val Seq(add, sub, mul, udiv, sdiv, urem, srem, shl, lshr, ashr, and, or, xor) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
89
90
91
      sdiv.vb.asSInt(32) shouldEqual -2
      srem.vb.asSInt(32) shouldEqual 12

Kunshan Wang's avatar
Kunshan Wang committed
92
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
93
94
    }

Kunshan Wang's avatar
Kunshan Wang committed
95
    ctx.closeContext()
Kunshan Wang's avatar
Kunshan Wang committed
96
97
98
  }

  "Binary operations" should "work on int<64>" in {
Kunshan Wang's avatar
Kunshan Wang committed
99
    val ctx = microVM.newContext()
Kunshan Wang's avatar
Kunshan Wang committed
100

Kunshan Wang's avatar
Kunshan Wang committed
101
102
103
    val func = ctx.func("@binops64")
    val arg0 = ctx.i64(42)
    val arg1 = ctx.i64(3)
Kunshan Wang's avatar
Kunshan Wang committed
104

Kunshan Wang's avatar
Kunshan Wang committed
105
106
    testFunc(ctx, func, Seq(arg0, arg1)) { (ctx, th, st, wp) =>
      val Seq(add, sub, mul, udiv, sdiv, urem, srem, shl, lshr, ashr, and, or, xor) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

      add.vb.asSInt(64) shouldEqual 45
      sub.vb.asSInt(64) shouldEqual 39
      mul.vb.asSInt(64) shouldEqual 126
      udiv.vb.asUInt(64) shouldEqual 14
      sdiv.vb.asSInt(64) shouldEqual 14
      urem.vb.asUInt(64) shouldEqual 0
      srem.vb.asSInt(64) shouldEqual 0
      shl.vb.asSInt(64) shouldEqual 336
      lshr.vb.asUInt(64) shouldEqual 5
      ashr.vb.asSInt(64) shouldEqual 5
      and.vb.asSInt(64) shouldEqual 2
      or.vb.asSInt(64) shouldEqual 43
      xor.vb.asSInt(64) shouldEqual 41

Kunshan Wang's avatar
Kunshan Wang committed
122
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
123
124
    }

Kunshan Wang's avatar
Kunshan Wang committed
125
126
    val arg2 = ctx.i64(-0x8000000000000000L)
    val arg3 = ctx.i64(-1L)
Kunshan Wang's avatar
Kunshan Wang committed
127

Kunshan Wang's avatar
Kunshan Wang committed
128
129
    testFunc(ctx, func, Seq(arg2, arg3)) { (ctx, th, st, wp) =>
      val Seq(add, sub, mul, udiv, sdiv, urem, srem, shl, lshr, ashr, and, or, xor) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
130
131
132
133

      sdiv.vb.asSInt(64) shouldEqual -0x8000000000000000L
      srem.vb.asSInt(64) shouldEqual 0

Kunshan Wang's avatar
Kunshan Wang committed
134
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
135
136
    }

Kunshan Wang's avatar
Kunshan Wang committed
137
138
139
140
    val arg4 = ctx.i64(13)
    val arg5 = ctx.i64(63)
    val arg6 = ctx.i64(64)
    val arg7 = ctx.i64(65)
Kunshan Wang's avatar
Kunshan Wang committed
141

Kunshan Wang's avatar
Kunshan Wang committed
142
143
    testFunc(ctx, func, Seq(arg4, arg5)) { (ctx, th, st, wp) =>
      val Seq(add, sub, mul, udiv, sdiv, urem, srem, shl, lshr, ashr, and, or, xor) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
144
145
146
147
148

      shl.vb.asUInt(64) shouldEqual BigInt("8000000000000000", 16)
      lshr.vb.asUInt(64) shouldEqual 0
      ashr.vb.asSInt(64) shouldEqual 0

Kunshan Wang's avatar
Kunshan Wang committed
149
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
150
151
    }

Kunshan Wang's avatar
Kunshan Wang committed
152
153
    testFunc(ctx, func, Seq(arg4, arg6)) { (ctx, th, st, wp) =>
      val Seq(add, sub, mul, udiv, sdiv, urem, srem, shl, lshr, ashr, and, or, xor) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
154
155
156
157
158

      shl.vb.asUInt(64) shouldEqual 13
      lshr.vb.asUInt(64) shouldEqual 13
      ashr.vb.asSInt(64) shouldEqual 13

Kunshan Wang's avatar
Kunshan Wang committed
159
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
160
161
    }

Kunshan Wang's avatar
Kunshan Wang committed
162
163
    testFunc(ctx, func, Seq(arg4, arg7)) { (ctx, th, st, wp) =>
      val Seq(add, sub, mul, udiv, sdiv, urem, srem, shl, lshr, ashr, and, or, xor) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
164
165
166
167
168

      shl.vb.asUInt(64) shouldEqual 26
      lshr.vb.asUInt(64) shouldEqual 6
      ashr.vb.asSInt(64) shouldEqual 6

Kunshan Wang's avatar
Kunshan Wang committed
169
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
170
171
    }

Kunshan Wang's avatar
Kunshan Wang committed
172
    ctx.closeContext()
Kunshan Wang's avatar
Kunshan Wang committed
173
174
175
  }

  "Binary operations" should "safely handle integer division by zero" in {
Kunshan Wang's avatar
Kunshan Wang committed
176
    val ctx = microVM.newContext()
Kunshan Wang's avatar
Kunshan Wang committed
177

Kunshan Wang's avatar
Kunshan Wang committed
178
179
180
181
    val func = ctx.func("@binops64_div0")
    val a = ctx.i64(42)
    val one = ctx.i64(1)
    val zero = ctx.i64(0)
Kunshan Wang's avatar
Kunshan Wang committed
182

Kunshan Wang's avatar
Kunshan Wang committed
183
184
185
    testFunc(ctx, func, Seq(a, zero, one, one, one)) { (ctx, th, st, wp) =>
      nameOf(ctx.curInst(st, 0)) shouldBe "@binops64_div0.v1.exc.trapexc"
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
186
    }
Kunshan Wang's avatar
Kunshan Wang committed
187
188
189
    testFunc(ctx, func, Seq(a, one, zero, one, one)) { (ctx, th, st, wp) =>
      nameOf(ctx.curInst(st, 0)) shouldBe "@binops64_div0.v1.exc.trapexc"
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
190
    }
Kunshan Wang's avatar
Kunshan Wang committed
191
192
193
    testFunc(ctx, func, Seq(a, one, one, zero, one)) { (ctx, th, st, wp) =>
      nameOf(ctx.curInst(st, 0)) shouldBe "@binops64_div0.v1.exc.trapexc"
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
194
    }
Kunshan Wang's avatar
Kunshan Wang committed
195
196
197
    testFunc(ctx, func, Seq(a, one, one, one, zero)) { (ctx, th, st, wp) =>
      nameOf(ctx.curInst(st, 0)) shouldBe "@binops64_div0.v1.exc.trapexc"
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
198
199
    }

Kunshan Wang's avatar
Kunshan Wang committed
200
    ctx.closeContext()
Kunshan Wang's avatar
Kunshan Wang committed
201
202
203
  }

  "Binary operations" should "work on float" in {
Kunshan Wang's avatar
Kunshan Wang committed
204
    val ctx = microVM.newContext()
Kunshan Wang's avatar
Kunshan Wang committed
205

Kunshan Wang's avatar
Kunshan Wang committed
206
207
208
    val func = ctx.func("@binops_f")
    val arg0 = ctx.handleFromFloat(45.0f)
    val arg1 = ctx.handleFromFloat(4.0f)
Kunshan Wang's avatar
Kunshan Wang committed
209

Kunshan Wang's avatar
Kunshan Wang committed
210
211
    testFunc(ctx, func, Seq(arg0, arg1)) { (ctx, th, st, wp) =>
      val Seq(fadd, fsub, fmul, fdiv, frem) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
212
213
214
215
216
217
218

      fadd.vb.asFloat shouldEqual 49.0f
      fsub.vb.asFloat shouldEqual 41.0f
      fmul.vb.asFloat shouldEqual 180.0f
      fdiv.vb.asFloat shouldEqual 11.25f
      frem.vb.asFloat shouldEqual 1.0f

Kunshan Wang's avatar
Kunshan Wang committed
219
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
220
221
    }

Kunshan Wang's avatar
Kunshan Wang committed
222
    val arg2 = ctx.handleFromFloat(Float.NaN)
Kunshan Wang's avatar
Kunshan Wang committed
223

Kunshan Wang's avatar
Kunshan Wang committed
224
225
    testFunc(ctx, func, Seq(arg0, arg2)) { (ctx, th, st, wp) =>
      val Seq(fadd, fsub, fmul, fdiv, frem) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
226
227
228
229
230
231
232

      fadd.vb.asFloat.isNaN shouldEqual true
      fsub.vb.asFloat.isNaN shouldEqual true
      fmul.vb.asFloat.isNaN shouldEqual true
      fdiv.vb.asFloat.isNaN shouldEqual true
      frem.vb.asFloat.isNaN shouldEqual true

Kunshan Wang's avatar
Kunshan Wang committed
233
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
234
235
    }

Kunshan Wang's avatar
Kunshan Wang committed
236
    ctx.closeContext()
Kunshan Wang's avatar
Kunshan Wang committed
237
238
239
  }

  "Binary operations" should "work on double" in {
Kunshan Wang's avatar
Kunshan Wang committed
240
    val ctx = microVM.newContext()
Kunshan Wang's avatar
Kunshan Wang committed
241

Kunshan Wang's avatar
Kunshan Wang committed
242
243
244
    val func = ctx.func("@binops_d")
    val arg0 = ctx.handleFromDouble(45.0d)
    val arg1 = ctx.handleFromDouble(4.0d)
Kunshan Wang's avatar
Kunshan Wang committed
245

Kunshan Wang's avatar
Kunshan Wang committed
246
247
    testFunc(ctx, func, Seq(arg0, arg1)) { (ctx, th, st, wp) =>
      val Seq(fadd, fsub, fmul, fdiv, frem) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
248
249
250
251
252
253
254

      fadd.vb.asDouble shouldEqual 49.0d
      fsub.vb.asDouble shouldEqual 41.0d
      fmul.vb.asDouble shouldEqual 180.0d
      fdiv.vb.asDouble shouldEqual 11.25d
      frem.vb.asDouble shouldEqual 1.0d

Kunshan Wang's avatar
Kunshan Wang committed
255
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
256
257
    }

Kunshan Wang's avatar
Kunshan Wang committed
258
    val arg2 = ctx.handleFromDouble(Double.NaN)
Kunshan Wang's avatar
Kunshan Wang committed
259

Kunshan Wang's avatar
Kunshan Wang committed
260
261
    testFunc(ctx, func, Seq(arg0, arg2)) { (ctx, th, st, wp) =>
      val Seq(fadd, fsub, fmul, fdiv, frem) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
262
263
264
265
266
267
268

      fadd.vb.asDouble.isNaN shouldEqual true
      fsub.vb.asDouble.isNaN shouldEqual true
      fmul.vb.asDouble.isNaN shouldEqual true
      fdiv.vb.asDouble.isNaN shouldEqual true
      frem.vb.asDouble.isNaN shouldEqual true

Kunshan Wang's avatar
Kunshan Wang committed
269
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
270
271
    }

Kunshan Wang's avatar
Kunshan Wang committed
272
    ctx.closeContext()
Kunshan Wang's avatar
Kunshan Wang committed
273
274
275
  }

  "Binary operations" should "work on vector types" in {
Kunshan Wang's avatar
Kunshan Wang committed
276
    val ctx = microVM.newContext()
Kunshan Wang's avatar
Kunshan Wang committed
277

Kunshan Wang's avatar
Kunshan Wang committed
278
    val func = ctx.func("@binops_vec")
Kunshan Wang's avatar
Kunshan Wang committed
279

Kunshan Wang's avatar
Kunshan Wang committed
280
281
282
283
284
285
    val a0 = ctx.handleFromConst("@4xI32_V3")
    val a1 = ctx.handleFromConst("@4xI32_V4")
    val a2 = ctx.handleFromConst("@4xF_V3")
    val a3 = ctx.handleFromConst("@4xF_V4")
    val a4 = ctx.handleFromConst("@2xD_V3")
    val a5 = ctx.handleFromConst("@2xD_V4")
Kunshan Wang's avatar
Kunshan Wang committed
286

Kunshan Wang's avatar
Kunshan Wang committed
287
288
    testFunc(ctx, func, Seq(a0, a1, a2, a3, a4, a5)) { (ctx, th, st, wp) =>
      val Seq(addi, subi, addf, subf, addd, subd) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
289
290
291
292
293
294
295
296

      addi.vb.asVec.map(_.asSInt(32)) shouldEqual Seq(11, 22, 33, 44)
      subi.vb.asVec.map(_.asSInt(32)) shouldEqual Seq(-9, -18, -27, -36)
      addf.vb.asVec.map(_.asFloat) shouldEqual Seq(11.0f, 22.0f, 33.0f, 44.0f)
      subf.vb.asVec.map(_.asFloat) shouldEqual Seq(-9.0f, -18.0f, -27.0f, -36.0f)
      addd.vb.asVec.map(_.asDouble) shouldEqual Seq(11.0d, 22.0d)
      subd.vb.asVec.map(_.asDouble) shouldEqual Seq(-9.0d, -18.0d)

Kunshan Wang's avatar
Kunshan Wang committed
297
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
298
299
    }

Kunshan Wang's avatar
Kunshan Wang committed
300
    ctx.closeContext()
Kunshan Wang's avatar
Kunshan Wang committed
301
  }
302
303

  "Comparing operations" should "work on int<64>" in {
Kunshan Wang's avatar
Kunshan Wang committed
304
    val ctx = microVM.newContext()
305

Kunshan Wang's avatar
Kunshan Wang committed
306
    val func = ctx.func("@cmp64")
307

Kunshan Wang's avatar
Kunshan Wang committed
308
309
    val a0 = ctx.i64(1)
    val a1 = ctx.i64(2)
310

Kunshan Wang's avatar
Kunshan Wang committed
311
312
    testFunc(ctx, func, Seq(a0, a1)) { (ctx, th, st, wp) =>
      val Seq(eq, ne, ult, ule, ugt, uge, slt, sle, sgt, sge) = ctx.dumpKeepalives(st, 0)
313
314
315
316
317
318
319
320
321
322
323
324

      eq.vb.asUInt(1) shouldEqual 0
      ne.vb.asUInt(1) shouldEqual 1
      ult.vb.asUInt(1) shouldEqual 1
      ule.vb.asUInt(1) shouldEqual 1
      ugt.vb.asUInt(1) shouldEqual 0
      uge.vb.asUInt(1) shouldEqual 0
      slt.vb.asUInt(1) shouldEqual 1
      sle.vb.asUInt(1) shouldEqual 1
      sgt.vb.asUInt(1) shouldEqual 0
      sge.vb.asUInt(1) shouldEqual 0

Kunshan Wang's avatar
Kunshan Wang committed
325
      Rebind(st, PassValues(Seq()))
326
327
    }

Kunshan Wang's avatar
Kunshan Wang committed
328
329
    testFunc(ctx, func, Seq(a0, a0)) { (ctx, th, st, wp) =>
      val Seq(eq, ne, ult, ule, ugt, uge, slt, sle, sgt, sge) = ctx.dumpKeepalives(st, 0)
330
331
332
333
334
335
336
337
338
339
340
341

      eq.vb.asUInt(1) shouldEqual 1
      ne.vb.asUInt(1) shouldEqual 0
      ult.vb.asUInt(1) shouldEqual 0
      ule.vb.asUInt(1) shouldEqual 1
      ugt.vb.asUInt(1) shouldEqual 0
      uge.vb.asUInt(1) shouldEqual 1
      slt.vb.asUInt(1) shouldEqual 0
      sle.vb.asUInt(1) shouldEqual 1
      sgt.vb.asUInt(1) shouldEqual 0
      sge.vb.asUInt(1) shouldEqual 1

Kunshan Wang's avatar
Kunshan Wang committed
342
      Rebind(st, PassValues(Seq()))
343
344
    }

Kunshan Wang's avatar
Kunshan Wang committed
345
    val a2 = ctx.i64(-3)
346

Kunshan Wang's avatar
Kunshan Wang committed
347
348
    testFunc(ctx, func, Seq(a0, a2)) { (ctx, th, st, wp) =>
      val Seq(eq, ne, ult, ule, ugt, uge, slt, sle, sgt, sge) = ctx.dumpKeepalives(st, 0)
349
350
351
352
353
354
355
356

      eq.vb.asUInt(1) shouldEqual 0
      ne.vb.asUInt(1) shouldEqual 1
      slt.vb.asUInt(1) shouldEqual 0
      sle.vb.asUInt(1) shouldEqual 0
      sgt.vb.asUInt(1) shouldEqual 1
      sge.vb.asUInt(1) shouldEqual 1

Kunshan Wang's avatar
Kunshan Wang committed
357
      Rebind(st, PassValues(Seq()))
358
359
    }

Kunshan Wang's avatar
Kunshan Wang committed
360
    ctx.closeContext()
361
362
363
  }

  "Comparing operations" should "work on float" in {
Kunshan Wang's avatar
Kunshan Wang committed
364
    val ctx = microVM.newContext()
365

Kunshan Wang's avatar
Kunshan Wang committed
366
    val func = ctx.func("@cmp_f")
367

Kunshan Wang's avatar
Kunshan Wang committed
368
369
    val a0 = ctx.handleFromFloat(1.0f)
    val a1 = ctx.handleFromFloat(2.0f)
370

Kunshan Wang's avatar
Kunshan Wang committed
371
372
    testFunc(ctx, func, Seq(a0, a1)) { (ctx, th, st, wp) =>
      val Seq(ftrue, ffalse, ford, foeq, fone, folt, fole, fogt, foge, funo, fueq, fune, fult, fule, fugt, fuge) = ctx.dumpKeepalives(st, 0)
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390

      ftrue.vb.asUInt(1) shouldEqual 1
      ffalse.vb.asUInt(1) shouldEqual 0
      ford.vb.asUInt(1) shouldEqual 1
      foeq.vb.asUInt(1) shouldEqual 0
      fone.vb.asUInt(1) shouldEqual 1
      folt.vb.asUInt(1) shouldEqual 1
      fole.vb.asUInt(1) shouldEqual 1
      fogt.vb.asUInt(1) shouldEqual 0
      foge.vb.asUInt(1) shouldEqual 0
      funo.vb.asUInt(1) shouldEqual 0
      fueq.vb.asUInt(1) shouldEqual 0
      fune.vb.asUInt(1) shouldEqual 1
      fult.vb.asUInt(1) shouldEqual 1
      fule.vb.asUInt(1) shouldEqual 1
      fugt.vb.asUInt(1) shouldEqual 0
      fuge.vb.asUInt(1) shouldEqual 0

Kunshan Wang's avatar
Kunshan Wang committed
391
      Rebind(st, PassValues(Seq()))
392
393
    }

Kunshan Wang's avatar
Kunshan Wang committed
394
395
    testFunc(ctx, func, Seq(a0, a0)) { (ctx, th, st, wp) =>
      val Seq(ftrue, ffalse, ford, foeq, fone, folt, fole, fogt, foge, funo, fueq, fune, fult, fule, fugt, fuge) = ctx.dumpKeepalives(st, 0)
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413

      ftrue.vb.asUInt(1) shouldEqual 1
      ffalse.vb.asUInt(1) shouldEqual 0
      ford.vb.asUInt(1) shouldEqual 1
      foeq.vb.asUInt(1) shouldEqual 1
      fone.vb.asUInt(1) shouldEqual 0
      folt.vb.asUInt(1) shouldEqual 0
      fole.vb.asUInt(1) shouldEqual 1
      fogt.vb.asUInt(1) shouldEqual 0
      foge.vb.asUInt(1) shouldEqual 1
      funo.vb.asUInt(1) shouldEqual 0
      fueq.vb.asUInt(1) shouldEqual 1
      fune.vb.asUInt(1) shouldEqual 0
      fult.vb.asUInt(1) shouldEqual 0
      fule.vb.asUInt(1) shouldEqual 1
      fugt.vb.asUInt(1) shouldEqual 0
      fuge.vb.asUInt(1) shouldEqual 1

Kunshan Wang's avatar
Kunshan Wang committed
414
      Rebind(st, PassValues(Seq()))
415
416
    }

Kunshan Wang's avatar
Kunshan Wang committed
417
    val a2 = ctx.handleFromFloat(Float.NaN)
418

Kunshan Wang's avatar
Kunshan Wang committed
419
420
    testFunc(ctx, func, Seq(a0, a2)) { (ctx, th, st, wp) =>
      val Seq(ftrue, ffalse, ford, foeq, fone, folt, fole, fogt, foge, funo, fueq, fune, fult, fule, fugt, fuge) = ctx.dumpKeepalives(st, 0)
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

      ftrue.vb.asUInt(1) shouldEqual 1
      ffalse.vb.asUInt(1) shouldEqual 0
      ford.vb.asUInt(1) shouldEqual 0
      foeq.vb.asUInt(1) shouldEqual 0
      fone.vb.asUInt(1) shouldEqual 0
      folt.vb.asUInt(1) shouldEqual 0
      fole.vb.asUInt(1) shouldEqual 0
      fogt.vb.asUInt(1) shouldEqual 0
      foge.vb.asUInt(1) shouldEqual 0
      funo.vb.asUInt(1) shouldEqual 1
      fueq.vb.asUInt(1) shouldEqual 1
      fune.vb.asUInt(1) shouldEqual 1
      fult.vb.asUInt(1) shouldEqual 1
      fule.vb.asUInt(1) shouldEqual 1
      fugt.vb.asUInt(1) shouldEqual 1
      fuge.vb.asUInt(1) shouldEqual 1

Kunshan Wang's avatar
Kunshan Wang committed
439
      Rebind(st, PassValues(Seq()))
440
    }
Kunshan Wang's avatar
Kunshan Wang committed
441
    ctx.closeContext()
442
443
444
  }

  "Comparing operations" should "work on double" in {
Kunshan Wang's avatar
Kunshan Wang committed
445
    val ctx = microVM.newContext()
446

Kunshan Wang's avatar
Kunshan Wang committed
447
    val func = ctx.func("@cmp_d")
448

Kunshan Wang's avatar
Kunshan Wang committed
449
450
    val a0 = ctx.handleFromDouble(1.0d)
    val a1 = ctx.handleFromDouble(2.0d)
451

Kunshan Wang's avatar
Kunshan Wang committed
452
453
    testFunc(ctx, func, Seq(a0, a1)) { (ctx, th, st, wp) =>
      val Seq(ftrue, ffalse, ford, foeq, fone, folt, fole, fogt, foge, funo, fueq, fune, fult, fule, fugt, fuge) = ctx.dumpKeepalives(st, 0)
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471

      ftrue.vb.asUInt(1) shouldEqual 1
      ffalse.vb.asUInt(1) shouldEqual 0
      ford.vb.asUInt(1) shouldEqual 1
      foeq.vb.asUInt(1) shouldEqual 0
      fone.vb.asUInt(1) shouldEqual 1
      folt.vb.asUInt(1) shouldEqual 1
      fole.vb.asUInt(1) shouldEqual 1
      fogt.vb.asUInt(1) shouldEqual 0
      foge.vb.asUInt(1) shouldEqual 0
      funo.vb.asUInt(1) shouldEqual 0
      fueq.vb.asUInt(1) shouldEqual 0
      fune.vb.asUInt(1) shouldEqual 1
      fult.vb.asUInt(1) shouldEqual 1
      fule.vb.asUInt(1) shouldEqual 1
      fugt.vb.asUInt(1) shouldEqual 0
      fuge.vb.asUInt(1) shouldEqual 0

Kunshan Wang's avatar
Kunshan Wang committed
472
      Rebind(st, PassValues(Seq()))
473
474
    }

Kunshan Wang's avatar
Kunshan Wang committed
475
476
    testFunc(ctx, func, Seq(a0, a0)) { (ctx, th, st, wp) =>
      val Seq(ftrue, ffalse, ford, foeq, fone, folt, fole, fogt, foge, funo, fueq, fune, fult, fule, fugt, fuge) = ctx.dumpKeepalives(st, 0)
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494

      ftrue.vb.asUInt(1) shouldEqual 1
      ffalse.vb.asUInt(1) shouldEqual 0
      ford.vb.asUInt(1) shouldEqual 1
      foeq.vb.asUInt(1) shouldEqual 1
      fone.vb.asUInt(1) shouldEqual 0
      folt.vb.asUInt(1) shouldEqual 0
      fole.vb.asUInt(1) shouldEqual 1
      fogt.vb.asUInt(1) shouldEqual 0
      foge.vb.asUInt(1) shouldEqual 1
      funo.vb.asUInt(1) shouldEqual 0
      fueq.vb.asUInt(1) shouldEqual 1
      fune.vb.asUInt(1) shouldEqual 0
      fult.vb.asUInt(1) shouldEqual 0
      fule.vb.asUInt(1) shouldEqual 1
      fugt.vb.asUInt(1) shouldEqual 0
      fuge.vb.asUInt(1) shouldEqual 1

Kunshan Wang's avatar
Kunshan Wang committed
495
      Rebind(st, PassValues(Seq()))
496
497
    }

Kunshan Wang's avatar
Kunshan Wang committed
498
    val a2 = ctx.handleFromDouble(Double.NaN)
499

Kunshan Wang's avatar
Kunshan Wang committed
500
501
    testFunc(ctx, func, Seq(a0, a2)) { (ctx, th, st, wp) =>
      val Seq(ftrue, ffalse, ford, foeq, fone, folt, fole, fogt, foge, funo, fueq, fune, fult, fule, fugt, fuge) = ctx.dumpKeepalives(st, 0)
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519

      ftrue.vb.asUInt(1) shouldEqual 1
      ffalse.vb.asUInt(1) shouldEqual 0
      ford.vb.asUInt(1) shouldEqual 0
      foeq.vb.asUInt(1) shouldEqual 0
      fone.vb.asUInt(1) shouldEqual 0
      folt.vb.asUInt(1) shouldEqual 0
      fole.vb.asUInt(1) shouldEqual 0
      fogt.vb.asUInt(1) shouldEqual 0
      foge.vb.asUInt(1) shouldEqual 0
      funo.vb.asUInt(1) shouldEqual 1
      fueq.vb.asUInt(1) shouldEqual 1
      fune.vb.asUInt(1) shouldEqual 1
      fult.vb.asUInt(1) shouldEqual 1
      fule.vb.asUInt(1) shouldEqual 1
      fugt.vb.asUInt(1) shouldEqual 1
      fuge.vb.asUInt(1) shouldEqual 1

Kunshan Wang's avatar
Kunshan Wang committed
520
      Rebind(st, PassValues(Seq()))
521
    }
Kunshan Wang's avatar
Kunshan Wang committed
522
    ctx.closeContext()
523
524
525
  }

  "Comparing operations" should "work on vectors" in {
Kunshan Wang's avatar
Kunshan Wang committed
526
    val ctx = microVM.newContext()
527

Kunshan Wang's avatar
Kunshan Wang committed
528
    val func = ctx.func("@cmp_vec")
529

Kunshan Wang's avatar
Kunshan Wang committed
530
531
532
533
534
535
    val a0 = ctx.handleFromConst("@4xI32_V5")
    val a1 = ctx.handleFromConst("@4xI32_V6")
    val a2 = ctx.handleFromConst("@4xF_V5")
    val a3 = ctx.handleFromConst("@4xF_V6")
    val a4 = ctx.handleFromConst("@2xD_V5")
    val a5 = ctx.handleFromConst("@2xD_V6")
536

Kunshan Wang's avatar
Kunshan Wang committed
537
538
    testFunc(ctx, func, Seq(a0, a1, a2, a3, a4, a5)) { (ctx, th, st, wp) =>
      val Seq(eq, slt, foeqf, fultf, foeqd, fultd) = ctx.dumpKeepalives(st, 0)
539
540
541
542
543
544
545
546

      eq.vb.asVec.map(_.asUInt(1)) shouldEqual Seq(1, 0, 0, 1)
      slt.vb.asVec.map(_.asUInt(1)) shouldEqual Seq(0, 1, 0, 0)
      foeqf.vb.asVec.map(_.asUInt(1)) shouldEqual Seq(1, 0, 0, 1)
      fultf.vb.asVec.map(_.asUInt(1)) shouldEqual Seq(0, 1, 0, 0)
      foeqd.vb.asVec.map(_.asUInt(1)) shouldEqual Seq(0, 1)
      fultd.vb.asVec.map(_.asUInt(1)) shouldEqual Seq(1, 0)

Kunshan Wang's avatar
Kunshan Wang committed
547
      Rebind(st, PassValues(Seq()))
548
549
    }

Kunshan Wang's avatar
Kunshan Wang committed
550
551
    val a6 = ctx.handleFromConst("@4xF_V7")
    val a7 = ctx.handleFromConst("@2xD_V7")
552

Kunshan Wang's avatar
Kunshan Wang committed
553
554
    testFunc(ctx, func, Seq(a0, a1, a2, a6, a4, a7)) { (ctx, th, st, wp) =>
      val Seq(eq, slt, foeqf, fultf, foeqd, fultd) = ctx.dumpKeepalives(st, 0)
555
556
557
558
559
560

      foeqf.vb.asVec.map(_.asUInt(1)) shouldEqual Seq(0, 0, 0, 0)
      fultf.vb.asVec.map(_.asUInt(1)) shouldEqual Seq(1, 1, 1, 1)
      foeqd.vb.asVec.map(_.asUInt(1)) shouldEqual Seq(0, 0)
      fultd.vb.asVec.map(_.asUInt(1)) shouldEqual Seq(1, 1)

Kunshan Wang's avatar
Kunshan Wang committed
561
      Rebind(st, PassValues(Seq()))
562
    }
Kunshan Wang's avatar
Kunshan Wang committed
563
    ctx.closeContext()
564
  }
565

566
  "Comparing operations" should "work on general reference types" in {
Kunshan Wang's avatar
Kunshan Wang committed
567
    val ctx = microVM.newContext()
568

Kunshan Wang's avatar
Kunshan Wang committed
569
    val func = ctx.func("@cmp_ref")
570

Kunshan Wang's avatar
Kunshan Wang committed
571
572
573
574
575
576
577
578
    val a0 = ctx.newFixed("@i64")
    val a1 = ctx.newFixed("@i64")
    val a2 = ctx.handleFromGlobal("@dummy_global1")
    val a3 = ctx.handleFromGlobal("@dummy_global2")
    val a4 = ctx.func("@dummy_func1")
    val a5 = ctx.func("@dummy_func2")
    val a6 = ctx.newStack(a4)
    val a7 = ctx.newStack(a5)
579

Kunshan Wang's avatar
Kunshan Wang committed
580
581
    testFunc(ctx, func, Seq(a0, a0, a2, a2, a4, a4, a6, a6)) { (ctx, th, st, wp) =>
      val Seq(req, rne, ieq, ine, feq, fne, seq, sne) = ctx.dumpKeepalives(st, 0)
582
583
584
585
586
587
588
589
590
591

      req.vb.asUInt(1) shouldEqual 1
      rne.vb.asUInt(1) shouldEqual 0
      ieq.vb.asUInt(1) shouldEqual 1
      ine.vb.asUInt(1) shouldEqual 0
      feq.vb.asUInt(1) shouldEqual 1
      fne.vb.asUInt(1) shouldEqual 0
      seq.vb.asUInt(1) shouldEqual 1
      sne.vb.asUInt(1) shouldEqual 0

Kunshan Wang's avatar
Kunshan Wang committed
592
      Rebind(st, PassValues(Seq()))
593
    }
594

Kunshan Wang's avatar
Kunshan Wang committed
595
596
    testFunc(ctx, func, Seq(a0, a1, a2, a3, a4, a5, a6, a7)) { (ctx, th, st, wp) =>
      val Seq(req, rne, ieq, ine, feq, fne, seq, sne) = ctx.dumpKeepalives(st, 0)
597
598
599
600
601
602
603
604
605
606

      req.vb.asUInt(1) shouldEqual 0
      rne.vb.asUInt(1) shouldEqual 1
      ieq.vb.asUInt(1) shouldEqual 0
      ine.vb.asUInt(1) shouldEqual 1
      feq.vb.asUInt(1) shouldEqual 0
      fne.vb.asUInt(1) shouldEqual 1
      seq.vb.asUInt(1) shouldEqual 0
      sne.vb.asUInt(1) shouldEqual 1

Kunshan Wang's avatar
Kunshan Wang committed
607
      Rebind(st, PassValues(Seq()))
608
    }
609

Kunshan Wang's avatar
Kunshan Wang committed
610
611
612
613
    val nr = ctx.handleFromConst("@NULLREF_I64")
    val ni = ctx.handleFromConst("@NULLIREF_I64")
    val nf = ctx.handleFromConst("@NULLFUNC")
    val ns = ctx.handleFromConst("@NULLSTACK")
614

Kunshan Wang's avatar
Kunshan Wang committed
615
616
    testFunc(ctx, func, Seq(nr, nr, ni, ni, nf, nf, ns, ns)) { (ctx, th, st, wp) =>
      val Seq(req, rne, ieq, ine, feq, fne, seq, sne) = ctx.dumpKeepalives(st, 0)
617
618
619
620
621
622
623
624
625
626

      req.vb.asUInt(1) shouldEqual 1
      rne.vb.asUInt(1) shouldEqual 0
      ieq.vb.asUInt(1) shouldEqual 1
      ine.vb.asUInt(1) shouldEqual 0
      feq.vb.asUInt(1) shouldEqual 1
      fne.vb.asUInt(1) shouldEqual 0
      seq.vb.asUInt(1) shouldEqual 1
      sne.vb.asUInt(1) shouldEqual 0

Kunshan Wang's avatar
Kunshan Wang committed
627
      Rebind(st, PassValues(Seq()))
628
    }
629

Kunshan Wang's avatar
Kunshan Wang committed
630
631
    testFunc(ctx, func, Seq(a0, nr, a2, ni, a4, nf, a6, ns)) { (ctx, th, st, wp) =>
      val Seq(req, rne, ieq, ine, feq, fne, seq, sne) = ctx.dumpKeepalives(st, 0)
632
633
634
635
636
637
638
639
640
641

      req.vb.asUInt(1) shouldEqual 0
      rne.vb.asUInt(1) shouldEqual 1
      ieq.vb.asUInt(1) shouldEqual 0
      ine.vb.asUInt(1) shouldEqual 1
      feq.vb.asUInt(1) shouldEqual 0
      fne.vb.asUInt(1) shouldEqual 1
      seq.vb.asUInt(1) shouldEqual 0
      sne.vb.asUInt(1) shouldEqual 1

Kunshan Wang's avatar
Kunshan Wang committed
642
      Rebind(st, PassValues(Seq()))
643
    }
644

Kunshan Wang's avatar
Kunshan Wang committed
645
    ctx.closeContext()
646
  }
647

648
  "Conversions" should "work on scalar types" in {
Kunshan Wang's avatar
Kunshan Wang committed
649
    val ctx = microVM.newContext()
650

Kunshan Wang's avatar
Kunshan Wang committed
651
    val func = ctx.func("@conv")
652

Kunshan Wang's avatar
Kunshan Wang committed
653
654
655
656
    val a0 = ctx.i32(0xfedcba98L)
    val a1 = ctx.i64(0x123456789abcdef0L)
    val a2 = ctx.handleFromFloat(1.5f)
    val a3 = ctx.handleFromDouble(6.25d)
657

Kunshan Wang's avatar
Kunshan Wang committed
658
659
    testFunc(ctx, func, Seq(a0, a1, a2, a3)) { (ctx, th, st, wp) =>
      val kas = ctx.dumpKeepalives(st, 0)
660

661
662
      val Seq(trunc, zext, sext, fptrunc, fpext, fptoui1, fptosi1, fptoui2, fptosi2, uitofp, sitofp) = kas.take(11)
      val Seq(bitcast1, bitcast2, bitcast3, bitcast4, ptrcast1, ptrcast2, ptrcast3, ptrcast4, ptrcast5, ptrcast6) = kas.drop(11)
Kunshan Wang's avatar
Kunshan Wang committed
663

664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
      trunc.vb.asUInt(32) shouldBe 0x9abcdef0L
      zext.vb.asUInt(64) shouldBe 0xfedcba98L
      sext.vb.asUInt(64) shouldBe BigInt("fffffffffedcba98", 16)

      fptrunc.vb.asFloat shouldBe 6.25f
      fpext.vb.asDouble shouldBe 1.5d

      fptoui1.vb.asSInt(64) shouldBe 6
      fptosi1.vb.asSInt(64) shouldBe 6
      fptoui2.vb.asSInt(32) shouldBe 1
      fptosi2.vb.asSInt(32) shouldBe 1
      uitofp.vb.asDouble shouldBe 0x123456789abcdef0L.doubleValue()
      sitofp.vb.asDouble shouldBe 0x123456789abcdef0L.doubleValue()

      bitcast1.vb.asSInt(32) shouldBe java.lang.Float.floatToRawIntBits(1.5f)
      bitcast2.vb.asSInt(64) shouldBe java.lang.Double.doubleToRawLongBits(6.25d)
      bitcast3.vb.asFloat shouldBe 1.5f
      bitcast4.vb.asDouble shouldBe 6.25d

Kunshan Wang's avatar
Kunshan Wang committed
683
684
685
686
      ptrcast1.vb.asPointer shouldBe 0x123456789abcdef0L
      ptrcast2.vb.asPointer shouldBe 0x123456789abcdef0L
      ptrcast3.vb.asSInt(64) shouldBe 0x123456789abcdef0L

687
688
689
690
      ptrcast4.vb.asSInt(64) shouldBe 0xdeadbeef13572468L
      ptrcast5.vb.asPointer shouldBe 0x55aa55aa5a5a5a5aL
      ptrcast6.vb.asInt shouldBe 0x13572468L

Kunshan Wang's avatar
Kunshan Wang committed
691
      Rebind(st, PassValues(Seq()))
692
    }
Kunshan Wang's avatar
Kunshan Wang committed
693
    val a5 = ctx.i64(-0x123456789abcdef0L)
694

Kunshan Wang's avatar
Kunshan Wang committed
695
696
    testFunc(ctx, func, Seq(a0, a5, a2, a3)) { (ctx, th, st, wp) =>
      val kas = ctx.dumpKeepalives(st, 0)
697
698
699

      val Seq(trunc, zext, sext, fptrunc, fpext, fptoui1, fptosi1, fptoui2, fptosi2, uitofp, sitofp) = kas.take(11)
      val Seq(bitcast1, bitcast2, bitcast3, bitcast4, ptrcast1, ptrcast2, ptrcast3, ptrcast4, ptrcast5, ptrcast6) = kas.drop(11)
700
701
702

      sitofp.vb.asDouble shouldBe (-0x123456789abcdef0L).doubleValue()

Kunshan Wang's avatar
Kunshan Wang committed
703
704
705
706
      ptrcast1.vb.asPointer shouldBe -0x123456789abcdef0L
      ptrcast2.vb.asPointer shouldBe -0x123456789abcdef0L
      ptrcast3.vb.asSInt(64) shouldBe -0x123456789abcdef0L

Kunshan Wang's avatar
Kunshan Wang committed
707
      Rebind(st, PassValues(Seq()))
708
709
    }

Kunshan Wang's avatar
Kunshan Wang committed
710
    ctx.closeContext()
711
712
713
  }

  "Conversions" should "work on vector types" in {
Kunshan Wang's avatar
Kunshan Wang committed
714
    val ctx = microVM.newContext()
715

Kunshan Wang's avatar
Kunshan Wang committed
716
    val func = ctx.func("@conv_vec")
717

Kunshan Wang's avatar
Kunshan Wang committed
718
719
720
    val a0 = ctx.handleFromConst("@4xI32_ABNORMALV1")
    val a1 = ctx.handleFromConst("@4xF_ABNORMALV1")
    val a2 = ctx.handleFromConst("@2xD_ABNORMALV1")
721

Kunshan Wang's avatar
Kunshan Wang committed
722
723
    testFunc(ctx, func, Seq(a0, a1, a2)) { (ctx, th, st, wp) =>
      val Seq(trunc, zext, sext, fptrunc, fpext) = ctx.dumpKeepalives(st, 0)
724
725
726
727
728
729
730
731

      trunc.vb.asVec.map(_.asUInt(16)) shouldBe Seq(0x5678L, 0xdef0L, 0xba98L, 0x3210L)
      zext.vb.asVec.map(_.asUInt(64)) shouldBe Seq(0x12345678L, 0x9abcdef0L, 0xfedcba98L, 0x76543210L)
      sext.vb.asVec.map(_.asUInt(64)) shouldBe Seq(0x12345678L, BigInt("ffffffff9abcdef0", 16), BigInt("fffffffffedcba98", 16), 0x76543210L)

      fptrunc.vb.asVec.map(_.asFloat) shouldBe Seq(1.0f, 1.5f)
      fpext.vb.asVec.map(_.asDouble) shouldBe Seq(1.0d, 1.5d, 2.0d, 2.5d)

Kunshan Wang's avatar
Kunshan Wang committed
732
      Rebind(st, PassValues(Seq()))
733
734
    }

Kunshan Wang's avatar
Kunshan Wang committed
735
    ctx.closeContext()
736
737
738
  }

  "The SELECT instruction" should "work on both scalars and vectors and allow per-element select" in {
Kunshan Wang's avatar
Kunshan Wang committed
739
    val ctx = microVM.newContext()
740

Kunshan Wang's avatar
Kunshan Wang committed
741
    val func = ctx.func("@select")
742

Kunshan Wang's avatar
Kunshan Wang committed
743
744
    testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
      val Seq(sel1, sel2, sel3, sel4, sel5) = ctx.dumpKeepalives(st, 0)
745
746
747
748
749
750
751
752
753

      sel1.vb.asSInt(64) shouldBe 2
      sel2.vb.asSInt(64) shouldBe 3

      sel3.vb.asVec.map(_.asSInt(32)) shouldBe Seq(0, 5, 6, 3)

      sel4.vb.asVec.map(_.asSInt(32)) shouldBe Seq(0, 1, 2, 3)
      sel5.vb.asVec.map(_.asSInt(32)) shouldBe Seq(4, 5, 6, 7)

Kunshan Wang's avatar
Kunshan Wang committed
754
      Rebind(st, PassValues(Seq()))
755
756
    }

Kunshan Wang's avatar
Kunshan Wang committed
757
    ctx.closeContext()
758
759
  }

760
  "Branching" should "work" in {
Kunshan Wang's avatar
Kunshan Wang committed
761
    val ctx = microVM.newContext()
762

Kunshan Wang's avatar
Kunshan Wang committed
763
    val func = ctx.func("@branch")
764

Kunshan Wang's avatar
Kunshan Wang committed
765
766
    val a0 = ctx.i64(0)
    val a1 = ctx.i64(1)
767

Kunshan Wang's avatar
Kunshan Wang committed
768
769
770
    testFunc(ctx, func, Seq(a0)) { (ctx, th, st, wp) =>
      nameOf(ctx.curInst(st, 0)) shouldBe "@branch.v1.iftrue.traptrue"
      Rebind(st, PassValues(Seq()))
771
772
    }

Kunshan Wang's avatar
Kunshan Wang committed
773
774
775
    testFunc(ctx, func, Seq(a1)) { (ctx, th, st, wp) =>
      nameOf(ctx.curInst(st, 0)) shouldBe "@branch.v1.iffalse.trapfalse"
      Rebind(st, PassValues(Seq()))
776
777
    }

Kunshan Wang's avatar
Kunshan Wang committed
778
    ctx.closeContext()
779
780
  }

Kunshan Wang's avatar
Kunshan Wang committed
781
  "SWTICH" should "work" in {
Kunshan Wang's avatar
Kunshan Wang committed
782
    val ctx = microVM.newContext()
783

Kunshan Wang's avatar
Kunshan Wang committed
784
    val func = ctx.func("@switch")
785

Kunshan Wang's avatar
Kunshan Wang committed
786
787
788
789
    val a0 = ctx.i64(0)
    val a1 = ctx.i64(1)
    val a2 = ctx.i64(2)
    val a3 = ctx.i64(3)
790

Kunshan Wang's avatar
Kunshan Wang committed
791
    def expectFlow(midTrapName: String, phiValue: BigInt): TrapHandlerFunction = { (ctx, th, st, wp) =>
792
      val M = midTrapName
Kunshan Wang's avatar
Kunshan Wang committed
793
      nameOf(ctx.curInst(st, 0)) match {
794
        case M => {}
Kunshan Wang's avatar
Kunshan Wang committed
795
        case "@switch.v1.exit.trapend" => {
Kunshan Wang's avatar
Kunshan Wang committed
796
          val Seq(v) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
797
          v.vb.asSInt(64) shouldBe phiValue
798
799
800
        }
        case trapName => fail("Trap %s should not be reached. Should reach %s.".format(trapName))
      }
Kunshan Wang's avatar
Kunshan Wang committed
801
      Rebind(st, PassValues(Seq()))
802
803
    }

Kunshan Wang's avatar
Kunshan Wang committed
804
805
806
807
    testFunc(ctx, func, Seq(a0))(expectFlow("@switch.v1.def.trapdef", 4))
    testFunc(ctx, func, Seq(a1))(expectFlow("@switch.v1.one.trapone", 5))
    testFunc(ctx, func, Seq(a2))(expectFlow("@switch.v1.two.traptwo", 6))
    testFunc(ctx, func, Seq(a3))(expectFlow("@switch.v1.three.trapthree", 7))
808

Kunshan Wang's avatar
Kunshan Wang committed
809
    ctx.closeContext()
810
  }
811

Kunshan Wang's avatar
Kunshan Wang committed
812
  "Parameters of a basic block" should "be assigned at the same time in CFG edges" in {
Kunshan Wang's avatar
Kunshan Wang committed
813
    val ctx = microVM.newContext()
814

Kunshan Wang's avatar
Kunshan Wang committed
815
    val func = ctx.func("@edge_asgn_test")
816

Kunshan Wang's avatar
Kunshan Wang committed
817
818
    testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
      val Seq(x, y) = ctx.dumpKeepalives(st, 0)
819

Kunshan Wang's avatar
Kunshan Wang committed
820
821
      ctx.handleToSInt(x.asInstanceOf[MuIntValue]) shouldEqual 2
      ctx.handleToSInt(y.asInstanceOf[MuIntValue]) shouldEqual 1
822

Kunshan Wang's avatar
Kunshan Wang committed
823
      Rebind(st, PassValues(Seq()))
824
825
    }

Kunshan Wang's avatar
Kunshan Wang committed
826
    ctx.closeContext()
827
  }
828
829

  "CALL and RET" should "work for normal returns" in {
Kunshan Wang's avatar
Kunshan Wang committed
830
    val ctx = microVM.newContext()
831

Kunshan Wang's avatar
Kunshan Wang committed
832
    val func = ctx.func("@call_ret")
833

Kunshan Wang's avatar
Kunshan Wang committed
834
835
    val a0 = ctx.i64(3)
    val a1 = ctx.i64(4)
Kunshan Wang's avatar
Kunshan Wang committed
836

Kunshan Wang's avatar
Kunshan Wang committed
837
838
    testFunc(ctx, func, Seq(a0, a1)) { (ctx, th, st, wp) =>
      val Seq(ss) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
839

840
      ss.vb.asInt shouldEqual 25
Kunshan Wang's avatar
Kunshan Wang committed
841

Kunshan Wang's avatar
Kunshan Wang committed
842
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
843
    }
Kunshan Wang's avatar
Kunshan Wang committed
844
    ctx.closeContext()
Kunshan Wang's avatar
Kunshan Wang committed
845
846
  }

Kunshan Wang's avatar
Kunshan Wang committed
847
  "CALL, THROW and the exception parameter" should "handle exceptions" in {
Kunshan Wang's avatar
Kunshan Wang committed
848
    val ctx = microVM.newContext()
Kunshan Wang's avatar
Kunshan Wang committed
849

Kunshan Wang's avatar
Kunshan Wang committed
850
    val func = ctx.func("@call_throw")
Kunshan Wang's avatar
Kunshan Wang committed
851

Kunshan Wang's avatar
Kunshan Wang committed
852
    val a0 = ctx.i64(3)
Kunshan Wang's avatar
Kunshan Wang committed
853

Kunshan Wang's avatar
Kunshan Wang committed
854
855
856
857
    testFunc(ctx, func, Seq(a0)) { (ctx, th, st, wp) =>
      nameOf(ctx.curInst(st, 0)) match {
        case "@call_throw.v1.nor.trapnor" => {
          val Seq(rv) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
858
859
          rv.vb.asInt shouldEqual 3
        }
Kunshan Wang's avatar
Kunshan Wang committed
860
        case "@call_throw.v1.exctrapexc" => {
Kunshan Wang's avatar
Kunshan Wang committed
861
862
863
864
          fail("Should not receive exception")
        }
      }

Kunshan Wang's avatar
Kunshan Wang committed
865
      Rebind(st, PassValues(Seq()))
Kunshan Wang's avatar
Kunshan Wang committed
866
867
    }

Kunshan Wang's avatar
Kunshan Wang committed
868
    val a1 = ctx.i64(0)
Kunshan Wang's avatar
Kunshan Wang committed
869

Kunshan Wang's avatar
Kunshan Wang committed
870
871
872
    testFunc(ctx, func, Seq(a1)) { (ctx, th, st, wp) =>
      nameOf(ctx.curInst(st, 0)) match {
        case "@call_throw.v1.nor.trapnor" => {
Kunshan Wang's avatar
Kunshan Wang committed
873
874
          fail("Should not return normally")
        }
Kunshan Wang's avatar
Kunshan Wang committed
875
876
        case "@call_throw.v1.exc.trapexc" => {
          val Seq(theExc) = ctx.dumpKeepalives(st, 0)
Kunshan Wang's avatar
Kunshan Wang committed
877
          theExc.vb.asRef shouldEqual 0L
Kunshan Wang's avatar
Kunshan Wang committed
878
879
880
        }
      }

Kunshan Wang's avatar
Kunshan Wang committed
881
      Rebind(st, PassValues(Seq()))
882
    }
Kunshan Wang's avatar
Kunshan Wang committed
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
    ctx.closeContext()
  }

  "CALL" should "be able to receive multiple return values or no return values" in {
    val ctx = microVM.newContext()

    val func = ctx.func("@call_multi_return")

    var checkpointReached = false

    testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
      nameOf(ctx.curInst(st, 0)) match {
        case "@checkpoint.v1.entry.trap" => {
          checkpointReached = true
        }
        case "@call_multi_return.v1.entry.trap" => {
          val Seq(a, b) = ctx.dumpKeepalives(st, 0)
          a.asSInt(64) shouldEqual 8
          b.asSInt(64) shouldEqual 7
          Rebind(st, PassValues(Seq()))
        }
      }

      Rebind(st, PassValues(Seq()))
    }

    checkpointReached shouldBe true

    ctx.closeContext()
912
  }
Kunshan Wang's avatar
Kunshan Wang committed
913
914

  "EXTRACTVALUE and INSERTVALUE" should "work" in {
Kunshan Wang's avatar
Kunshan Wang committed
915
    val ctx = microVM.newContext()
Kunshan Wang's avatar
Kunshan Wang committed
916

Kunshan Wang's avatar
Kunshan Wang committed
917
    val func = ctx.func("@aggregate_struct")
Kunshan Wang's avatar
Kunshan Wang committed
918

Kunshan Wang's avatar
Kunshan Wang committed
919
920
    testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
      val Seq(f1, f12) = ctx.dumpKeepalives(st, 0)
921

Kunshan Wang's avatar
Kunshan Wang committed
922
923
      f1.vb.asSInt(64) shouldEqual 2
      f12.vb.asSInt(64) shouldEqual 7