Skip to content

Commit

Permalink
Implement extend instructions in interpreter (WebAssembly#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
binji authored Aug 17, 2017
1 parent fae1e3a commit 2f7592b
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 1 deletion.
6 changes: 6 additions & 0 deletions interpreter/binary/decode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,12 @@ let rec instr s =
| 0xbe -> f32_reinterpret_i32
| 0xbf -> f64_reinterpret_i64

| 0xc0 -> i32_extend8_s
| 0xc1 -> i32_extend16_s
| 0xc2 -> i64_extend8_s
| 0xc3 -> i64_extend16_s
| 0xc4 -> i64_extend32_s

| b -> illegal s pos b

and instr_block s = List.rev (instr_block' s [])
Expand Down
6 changes: 6 additions & 0 deletions interpreter/binary/encode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,16 @@ let encode m =
| Unary (I32 I32Op.Clz) -> op 0x67
| Unary (I32 I32Op.Ctz) -> op 0x68
| Unary (I32 I32Op.Popcnt) -> op 0x69
| Unary (I32 I32Op.Extend8S) -> op 0xc0
| Unary (I32 I32Op.Extend16S) -> op 0xc1
| Unary (I32 I32Op.Extend32S) -> assert false

| Unary (I64 I64Op.Clz) -> op 0x79
| Unary (I64 I64Op.Ctz) -> op 0x7a
| Unary (I64 I64Op.Popcnt) -> op 0x7b
| Unary (I64 I64Op.Extend8S) -> op 0xc2
| Unary (I64 I64Op.Extend16S) -> op 0xc3
| Unary (I64 I64Op.Extend32S) -> op 0xc4

| Unary (F32 F32Op.Abs) -> op 0x8b
| Unary (F32 F32Op.Neg) -> op 0x8c
Expand Down
3 changes: 3 additions & 0 deletions interpreter/exec/eval_numeric.ml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ struct
| Clz -> IXX.clz
| Ctz -> IXX.ctz
| Popcnt -> IXX.popcnt
| Extend8S -> IXX.extend8_s
| Extend16S -> IXX.extend16_s
| Extend32S -> IXX.extend32_s
in fun v -> to_value (f (of_value 1 v))

let binop op =
Expand Down
11 changes: 11 additions & 0 deletions interpreter/exec/int.ml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ sig
val clz : t -> t
val ctz : t -> t
val popcnt : t -> t
val extend8_s : t -> t
val extend16_s : t -> t
val extend32_s : t -> t
val eqz : t -> bool
val eq : t -> t -> bool
val ne : t -> t -> bool
Expand Down Expand Up @@ -201,6 +204,14 @@ struct
loop acc' (i - 1) (Rep.shift_right_logical n 1)
in Rep.of_int (loop 0 Rep.bitwidth x)

let extendn_s n x =
let shift = Rep.bitwidth - n in
Rep.shift_right (Rep.shift_left x shift) shift

let extend8_s x = extendn_s 8 x
let extend16_s x = extendn_s 16 x
let extend32_s x = extendn_s 32 x

let eqz x = x = Rep.zero

let eq x y = x = y
Expand Down
2 changes: 1 addition & 1 deletion interpreter/syntax/ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ open Types

module IntOp =
struct
type unop = Clz | Ctz | Popcnt
type unop = Clz | Ctz | Popcnt | Extend8S | Extend16S | Extend32S
type binop = Add | Sub | Mul | DivS | DivU | RemS | RemU
| And | Or | Xor | Shl | ShrS | ShrU | Rotl | Rotr
type testop = Eqz
Expand Down
6 changes: 6 additions & 0 deletions interpreter/syntax/operators.ml
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,12 @@ let i64_reinterpret_f64 = Convert (I64 I64Op.ReinterpretFloat)
let f32_reinterpret_i32 = Convert (F32 F32Op.ReinterpretInt)
let f64_reinterpret_i64 = Convert (F64 F64Op.ReinterpretInt)

let i32_extend8_s = Unary (I32 I32Op.Extend8S)
let i32_extend16_s = Unary (I32 I32Op.Extend16S)
let i64_extend8_s = Unary (I64 I64Op.Extend8S)
let i64_extend16_s = Unary (I64 I64Op.Extend16S)
let i64_extend32_s = Unary (I64 I64Op.Extend32S)

let current_memory = CurrentMemory
let grow_memory = GrowMemory

3 changes: 3 additions & 0 deletions interpreter/text/arrange.ml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ struct
| Clz -> "clz"
| Ctz -> "ctz"
| Popcnt -> "popcnt"
| Extend8S -> "extend8_s"
| Extend16S -> "extend16_s"
| Extend32S -> "extend32_s"

let binop xx = function
| Add -> "add"
Expand Down
3 changes: 3 additions & 0 deletions interpreter/text/lexer.mll
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ rule token = parse
| (ixx as t)".clz" { UNARY (intop t i32_clz i64_clz) }
| (ixx as t)".ctz" { UNARY (intop t i32_ctz i64_ctz) }
| (ixx as t)".popcnt" { UNARY (intop t i32_popcnt i64_popcnt) }
| (ixx as t)".extend8_s" { UNARY (intop t i32_extend8_s i64_extend8_s) }
| (ixx as t)".extend16_s" { UNARY (intop t i32_extend16_s i64_extend16_s) }
| "i64.extend32_s" { UNARY i64_extend32_s }
| (fxx as t)".neg" { UNARY (floatop t f32_neg f64_neg) }
| (fxx as t)".abs" { UNARY (floatop t f32_abs f64_abs) }
| (fxx as t)".sqrt" { UNARY (floatop t f32_sqrt f64_sqrt) }
Expand Down
18 changes: 18 additions & 0 deletions test/core/i32.wast
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
(func (export "clz") (param $x i32) (result i32) (i32.clz (get_local $x)))
(func (export "ctz") (param $x i32) (result i32) (i32.ctz (get_local $x)))
(func (export "popcnt") (param $x i32) (result i32) (i32.popcnt (get_local $x)))
(func (export "extend8_s") (param $x i32) (result i32) (i32.extend8_s (get_local $x)))
(func (export "extend16_s") (param $x i32) (result i32) (i32.extend16_s (get_local $x)))
(func (export "eqz") (param $x i32) (result i32) (i32.eqz (get_local $x)))
(func (export "eq") (param $x i32) (param $y i32) (result i32) (i32.eq (get_local $x) (get_local $y)))
(func (export "ne") (param $x i32) (param $y i32) (result i32) (i32.ne (get_local $x) (get_local $y)))
Expand Down Expand Up @@ -264,6 +266,22 @@
(assert_return (invoke "popcnt" (i32.const 0x55555555)) (i32.const 16))
(assert_return (invoke "popcnt" (i32.const 0xDEADBEEF)) (i32.const 24))

(assert_return (invoke "extend8_s" (i32.const 0)) (i32.const 0))
(assert_return (invoke "extend8_s" (i32.const 0x7f)) (i32.const 127))
(assert_return (invoke "extend8_s" (i32.const 0x80)) (i32.const -128))
(assert_return (invoke "extend8_s" (i32.const 0xff)) (i32.const -1))
(assert_return (invoke "extend8_s" (i32.const 0x012345_00)) (i32.const 0))
(assert_return (invoke "extend8_s" (i32.const 0xfedcba_80)) (i32.const -0x80))
(assert_return (invoke "extend8_s" (i32.const -1)) (i32.const -1))

(assert_return (invoke "extend16_s" (i32.const 0)) (i32.const 0))
(assert_return (invoke "extend16_s" (i32.const 0x7fff)) (i32.const 32767))
(assert_return (invoke "extend16_s" (i32.const 0x8000)) (i32.const -32768))
(assert_return (invoke "extend16_s" (i32.const 0xffff)) (i32.const -1))
(assert_return (invoke "extend16_s" (i32.const 0x0123_0000)) (i32.const 0))
(assert_return (invoke "extend16_s" (i32.const 0xfedc_8000)) (i32.const -0x8000))
(assert_return (invoke "extend16_s" (i32.const -1)) (i32.const -1))

(assert_return (invoke "eqz" (i32.const 0)) (i32.const 1))
(assert_return (invoke "eqz" (i32.const 1)) (i32.const 0))
(assert_return (invoke "eqz" (i32.const 0x80000000)) (i32.const 0))
Expand Down
30 changes: 30 additions & 0 deletions test/core/i64.wast
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
(func (export "clz") (param $x i64) (result i64) (i64.clz (get_local $x)))
(func (export "ctz") (param $x i64) (result i64) (i64.ctz (get_local $x)))
(func (export "popcnt") (param $x i64) (result i64) (i64.popcnt (get_local $x)))
(func (export "extend8_s") (param $x i64) (result i64) (i64.extend8_s (get_local $x)))
(func (export "extend16_s") (param $x i64) (result i64) (i64.extend16_s (get_local $x)))
(func (export "extend32_s") (param $x i64) (result i64) (i64.extend32_s (get_local $x)))
(func (export "eqz") (param $x i64) (result i32) (i64.eqz (get_local $x)))
(func (export "eq") (param $x i64) (param $y i64) (result i32) (i64.eq (get_local $x) (get_local $y)))
(func (export "ne") (param $x i64) (param $y i64) (result i32) (i64.ne (get_local $x) (get_local $y)))
Expand Down Expand Up @@ -264,6 +267,33 @@
(assert_return (invoke "popcnt" (i64.const 0x99999999AAAAAAAA)) (i64.const 32))
(assert_return (invoke "popcnt" (i64.const 0xDEADBEEFDEADBEEF)) (i64.const 48))

(assert_return (invoke "extend8_s" (i64.const 0)) (i64.const 0))
(assert_return (invoke "extend8_s" (i64.const 0x7f)) (i64.const 127))
(assert_return (invoke "extend8_s" (i64.const 0x80)) (i64.const -128))
(assert_return (invoke "extend8_s" (i64.const 0xff)) (i64.const -1))
(assert_return (invoke "extend8_s" (i64.const 0x01234567_89abcd_00)) (i64.const 0))
(assert_return (invoke "extend8_s" (i64.const 0xfedcba98_765432_80)) (i64.const -0x80))
(assert_return (invoke "extend8_s" (i64.const -1)) (i64.const -1))

(assert_return (invoke "extend16_s" (i64.const 0)) (i64.const 0))
(assert_return (invoke "extend16_s" (i64.const 0x7fff)) (i64.const 32767))
(assert_return (invoke "extend16_s" (i64.const 0x8000)) (i64.const -32768))
(assert_return (invoke "extend16_s" (i64.const 0xffff)) (i64.const -1))
(assert_return (invoke "extend16_s" (i64.const 0x12345678_9abc_0000)) (i64.const 0))
(assert_return (invoke "extend16_s" (i64.const 0xfedcba98_7654_8000)) (i64.const -0x8000))
(assert_return (invoke "extend16_s" (i64.const -1)) (i64.const -1))

(assert_return (invoke "extend32_s" (i64.const 0)) (i64.const 0))
(assert_return (invoke "extend32_s" (i64.const 0x7fff)) (i64.const 32767))
(assert_return (invoke "extend32_s" (i64.const 0x8000)) (i64.const 32768))
(assert_return (invoke "extend32_s" (i64.const 0xffff)) (i64.const 65535))
(assert_return (invoke "extend32_s" (i64.const 0x7fffffff)) (i64.const 0x7fffffff))
(assert_return (invoke "extend32_s" (i64.const 0x80000000)) (i64.const -0x80000000))
(assert_return (invoke "extend32_s" (i64.const 0xffffffff)) (i64.const -1))
(assert_return (invoke "extend32_s" (i64.const 0x01234567_00000000)) (i64.const 0))
(assert_return (invoke "extend32_s" (i64.const 0xfedcba98_80000000)) (i64.const -0x80000000))
(assert_return (invoke "extend32_s" (i64.const -1)) (i64.const -1))

(assert_return (invoke "eqz" (i64.const 0)) (i32.const 1))
(assert_return (invoke "eqz" (i64.const 1)) (i32.const 0))
(assert_return (invoke "eqz" (i64.const 0x8000000000000000)) (i32.const 0))
Expand Down

0 comments on commit 2f7592b

Please sign in to comment.