diff --git a/src/compile.ml b/src/compile.ml index 24f8c153656..15c0d5d9399 100644 --- a/src/compile.ml +++ b/src/compile.ml @@ -3825,6 +3825,28 @@ and compile_exp (env : E.t) exp = sanitize_word_result Type.Word16) | "shrs" -> compile_kernel_as SR.UnboxedWord32 (G.i (Binary (Wasm.Values.I32 I32Op.ShrS))) | "shrs64" -> compile_kernel_as SR.UnboxedInt64 (G.i (Binary (Wasm.Values.I64 I64Op.ShrS))) + | "btst8" -> compile_kernel_as SR.Vanilla ( + let ty = Type.Word8 in + let (set_b, get_b) = new_local env "b" + in lsb_adjust ty ^^ set_b ^^ lsb_adjust ty ^^ + compile_unboxed_one ^^ get_b ^^ clamp_shift_amount ty ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Shl)) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.And))) + | "btst16" -> compile_kernel_as SR.Vanilla ( + let ty = Type.Word16 in + let (set_b, get_b) = new_local env "b" + in lsb_adjust ty ^^ set_b ^^ lsb_adjust ty ^^ + compile_unboxed_one ^^ get_b ^^ clamp_shift_amount ty ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Shl)) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.And))) + | "btst" -> compile_kernel_as SR.UnboxedWord32 ( + let (set_b, get_b) = new_local env "b" + in set_b ^^ compile_unboxed_one ^^ get_b ^^ G.i (Binary (Wasm.Values.I32 I32Op.Shl)) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.And))) + | "btst64" -> compile_kernel_as SR.UnboxedInt64 ( + let (set_b, get_b) = new_local64 env "b" + in set_b ^^ compile_const_64 1L ^^ get_b ^^ G.i (Binary (Wasm.Values.I64 I64Op.Shl)) ^^ + G.i (Binary (Wasm.Values.I64 I64Op.And))) | _ -> SR.Unreachable, todo "compile_exp" (Arrange_ir.exp pe) (G.i Unreachable) end diff --git a/src/prelude.ml b/src/prelude.ml index 41deded215d..2de8f86c42a 100644 --- a/src/prelude.ml +++ b/src/prelude.ml @@ -63,21 +63,25 @@ func shrsWord8(w : Word8, amount : Word8) : Word8 = (prim "shrs8" : (Word8, Word func popcntWord8(w : Word8) : Word8 = (prim "popcnt8" : Word8 -> Word8) w; func clzWord8(w : Word8) : Word8 = (prim "clz8" : Word8 -> Word8) w; func ctzWord8(w : Word8) : Word8 = (prim "ctz8" : Word8 -> Word8) w; +func btstWord8(w : Word8, amount : Word8) : Bool = (prim "btst8" : (Word8, Word8) -> Word8) (w, amount) != (0 : Word8); func shrsWord16(w : Word16, amount : Word16) : Word16 = (prim "shrs16" : (Word16, Word16) -> Word16) (w, amount); func popcntWord16(w : Word16) : Word16 = (prim "popcnt16" : Word16 -> Word16) w; func clzWord16(w : Word16) : Word16 = (prim "clz16" : Word16 -> Word16) w; func ctzWord16(w : Word16) : Word16 = (prim "ctz16" : Word16 -> Word16) w; +func btstWord16(w : Word16, amount : Word16) : Bool = (prim "btst16" : (Word16, Word16) -> Word16) (w, amount) != (0 : Word16); func shrsWord32(w : Word32, amount : Word32) : Word32 = (prim "shrs" : (Word32, Word32) -> Word32) (w, amount); func popcntWord32(w : Word32) : Word32 = (prim "popcnt" : Word32 -> Word32) w; func clzWord32(w : Word32) : Word32 = (prim "clz" : Word32 -> Word32) w; func ctzWord32(w : Word32) : Word32 = (prim "ctz" : Word32 -> Word32) w; +func btstWord32(w : Word32, amount : Word32) : Bool = (prim "btst" : (Word32, Word32) -> Word32) (w, amount) != (0 : Word32); func shrsWord64(w : Word64, amount : Word64) : Word64 = (prim "shrs64" : (Word64, Word64) -> Word64) (w, amount); func popcntWord64(w : Word64) : Word64 = (prim "popcnt64" : Word64 -> Word64) w; func clzWord64(w : Word64) : Word64 = (prim "clz64" : Word64 -> Word64) w; func ctzWord64(w : Word64) : Word64 = (prim "ctz64" : Word64 -> Word64) w; +func btstWord64(w : Word64, amount : Word64) : Bool = (prim "btst64" : (Word64, Word64) -> Word64) (w, amount) != (0 : Word64); // This would be nicer as a objects, but lets do them as functions @@ -230,6 +234,18 @@ let prim = function | Word64 w -> Word64 (Word64.ctz w) | _ -> failwith "ctz") + | "btst8" + | "btst16" + | "btst" + | "btst64" -> fun v k -> + let w, a = as_pair v + in k (match w with + | Word8 y -> Word8 Word8.(and_ y (shl (of_int_u 1) (as_word8 a))) + | Word16 y -> Word16 Word16.(and_ y (shl (of_int_u 1) (as_word16 a))) + | Word32 y -> Word32 (Word32.and_ y (Word32.shl 1l (as_word32 a))) + | Word64 y -> Word64 (Word64.and_ y (Word64.shl 1L (as_word64 a))) + | _ -> failwith "btst") + | "print" -> fun v k -> Printf.printf "%s%!" (as_text v); k unit | "printInt" -> fun v k -> Printf.printf "%d%!" (Int.to_int (as_int v)); k unit | "@serialize" -> fun v k -> k (Serialized v) diff --git a/test/run-dfinity/ok/counter-class.wasm.stderr.ok b/test/run-dfinity/ok/counter-class.wasm.stderr.ok index 18f6f46ecc8..cb1f1836617 100644 --- a/test/run-dfinity/ok/counter-class.wasm.stderr.ok +++ b/test/run-dfinity/ok/counter-class.wasm.stderr.ok @@ -18,31 +18,31 @@ non-closed actor: (ActorE (FuncE read (shared 1 -> 0) - (params $60) + (params $68) () (BlockE (LetD - (TupP (VarP $58)) - (TupE (CallE ( 1 -> 1) (PrimE @deserialize) (VarE $60))) + (TupP (VarP $66)) + (TupE (CallE ( 1 -> 1) (PrimE @deserialize) (VarE $68))) ) (CallE ( 1 -> 0) (FuncE $lambda ( 1 -> 0) - (params $57) + (params $65) () - (CallE ( 1 -> 0) (VarE $57) (VarE c)) + (CallE ( 1 -> 0) (VarE $65) (VarE c)) ) (FuncE $lambda ( 1 -> 0) - (params $59) + (params $67) () (CallE (shared 1 -> 0) - (VarE $58) - (CallE ( 1 -> 1) (PrimE @serialize) (VarE $59)) + (VarE $66) + (CallE ( 1 -> 1) (PrimE @serialize) (VarE $67)) ) ) ) diff --git a/test/run/ok/words.run-ir.ok b/test/run/ok/words.run-ir.ok index 15c4b3b8c29..a3f996d1a6f 100644 --- a/test/run/ok/words.run-ir.ok +++ b/test/run/ok/words.run-ir.ok @@ -19,6 +19,9 @@ 61 61 49 49 5 5 +set +clear +set 8912765 8912765 4286054531 -8912765 4286054530 -8912766 @@ -40,6 +43,9 @@ 29 29 17 17 5 5 +set +clear +set 55734 -9802 9802 9802 9801 9801 @@ -60,6 +66,9 @@ 13 13 1 1 5 5 +set +clear +set 34 34 222 -34 221 -35 @@ -80,3 +89,6 @@ 5 5 0 0 3 3 +set +clear +set diff --git a/test/run/ok/words.run-low.ok b/test/run/ok/words.run-low.ok index 15c4b3b8c29..a3f996d1a6f 100644 --- a/test/run/ok/words.run-low.ok +++ b/test/run/ok/words.run-low.ok @@ -19,6 +19,9 @@ 61 61 49 49 5 5 +set +clear +set 8912765 8912765 4286054531 -8912765 4286054530 -8912766 @@ -40,6 +43,9 @@ 29 29 17 17 5 5 +set +clear +set 55734 -9802 9802 9802 9801 9801 @@ -60,6 +66,9 @@ 13 13 1 1 5 5 +set +clear +set 34 34 222 -34 221 -35 @@ -80,3 +89,6 @@ 5 5 0 0 3 3 +set +clear +set diff --git a/test/run/ok/words.run.ok b/test/run/ok/words.run.ok index 15c4b3b8c29..a3f996d1a6f 100644 --- a/test/run/ok/words.run.ok +++ b/test/run/ok/words.run.ok @@ -19,6 +19,9 @@ 61 61 49 49 5 5 +set +clear +set 8912765 8912765 4286054531 -8912765 4286054530 -8912766 @@ -40,6 +43,9 @@ 29 29 17 17 5 5 +set +clear +set 55734 -9802 9802 9802 9801 9801 @@ -60,6 +66,9 @@ 13 13 1 1 5 5 +set +clear +set 34 34 222 -34 221 -35 @@ -80,3 +89,6 @@ 5 5 0 0 3 3 +set +clear +set diff --git a/test/run/words.as b/test/run/words.as index a6a2cd0128a..479df6a7f2a 100644 --- a/test/run/words.as +++ b/test/run/words.as @@ -1,5 +1,8 @@ // CHECK: func $start +func printBit(a : Bool) { print(if a "set" else "clear"); print "\n" }; + + func checkpointAlpha() {}; func checkpointBravo() {}; func checkpointCharlie() {}; @@ -53,6 +56,9 @@ func checkpointJuliett() {}; printW64ln(popcntWord64 d); // -15 = 0xfffffffffffffff1 = 0b1111_..._1111_1111_0001 (population = 61) printW64ln(clzWord64 e); // 20000 = 0x0000000000004e20 (leading zeros = 49) printW64ln(ctzWord64 e); // 20000 = 0x0000000000004e20 (trailing zeros = 5) + printBit(btstWord64(e, 5 : Word64)); // 20000 = 0x0000000000004e20 (result = true) + printBit(btstWord64(e, 63 : Word64)); // 20000 = 0x0000000000004e20 (result = false) + printBit(btstWord64(e, 69 : Word64)); // 20000 = 0x0000000000004e20 (mod 64, result = true) assert (3 : Word64 ** (4 : Word64) == (81 : Word64)); assert (3 : Word64 ** (7 : Word64) == (2187 : Word64)); @@ -105,6 +111,9 @@ func checkpointJuliett() {}; printW32ln(popcntWord32 d); // -15 = 0xfffffff1 = 0b1111_1111_1111_1111_1111_1111_1111_0001 (population = 29) printW32ln(clzWord32 e); // 20000 = 0x00004e20 (leading zeros = 17) printW32ln(ctzWord32 e); // 20000 = 0x00004e20 (trailing zeros = 5) + printBit(btstWord32(e, 5 : Word32)); // 20000 = 0x00004e20 (result = true) + printBit(btstWord32(e, 31 : Word32)); // 20000 = 0x00004e20 (result = false) + printBit(btstWord32(e, 37 : Word32)); // 20000 = 0x00004e20 (mod 32, result = true) assert (3 : Word32 ** (4 : Word32) == (81 : Word32)); assert (3 : Word32 ** (7 : Word32) == (2187 : Word32)); @@ -180,6 +189,9 @@ func checkpointJuliett() {}; printW16ln(popcntWord16 d); // -15 = 0xfff1 = 0b1111_1111_1111_0001 (population = 13) printW16ln(clzWord16 e); // 20000 = 0x4e20 (leading zeros = 1) printW16ln(ctzWord16 e); // 20000 = 0x4e20 (trailing zeros = 5) + printBit(btstWord16(e, 5 : Word16)); // 20000 = 0x4e20 (result = true) + printBit(btstWord16(e, 15 : Word16)); // 20000 = 0x4e20 (result = false) + printBit(btstWord16(e, 21 : Word16)); // 20000 = 0x4e20 (mod 16, result = true) assert (3 : Word16 ** (0 : Word16) == (1 : Word16)); @@ -251,6 +263,9 @@ func checkpointJuliett() {}; printW8ln(popcntWord8 d); // -15 = 0xf1 = 0b1111_0001 (population = 5) printW8ln(clzWord8 e); // 200 = 0xC8 (leading zeros = 0) printW8ln(ctzWord8 e); // 200 = 0xC8 (trailing zeros = 3) + printBit(btstWord8(e, 3 : Word8)); // 200 = 0xC8 (result = true) + printBit(btstWord8(e, 5 : Word8)); // 200 = 0xC8 (result = false) + printBit(btstWord8(e, 11 : Word8)); // 200 = 0xC8 (mod 8, result = true) assert (3 : Word8 ** (0 : Word8) == (1 : Word8)); assert (3 : Word8 ** (3 : Word8) == (27 : Word8));