diff --git a/Changelog.md b/Changelog.md index 33dfdf4bfc3..b94517c8547 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,6 +15,7 @@ * The actor literal, `actor `, will trap if the binary representation of of the textually encoded principal `` contains strictly more than 29 bytes. + * bugfix: fully implement `Region.loadXXX/storeXXX` for `Int8`, `Int16` and `Float`. ## 0.10.1 (2023-10-16) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index f1288007c39..7d94bb1e5c4 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -10656,34 +10656,34 @@ and compile_prim_invocation (env : E.t) ae p es at = compile_exp_as env ae SR.Vanilla e2 ^^ Region.store_blob env - | OtherPrim ("regionLoadNat8"), [e0; e1] -> + | OtherPrim (("regionLoadNat8" | "regionLoadInt8" as p)), [e0; e1] -> SR.Vanilla, compile_exp_as env ae SR.Vanilla e0 ^^ compile_exp_as env ae SR.UnboxedWord64 e1 ^^ Region.load_word8 env ^^ - TaggedSmallWord.msb_adjust Type.Nat8 + TaggedSmallWord.msb_adjust Type.(if p = "regionLoadNat8" then Nat8 else Int8) - | OtherPrim ("regionStoreNat8"), [e0; e1; e2] -> + | OtherPrim (("regionStoreNat8" | "regionStoreInt8") as p), [e0; e1; e2] -> SR.unit, compile_exp_as env ae SR.Vanilla e0 ^^ compile_exp_as env ae SR.UnboxedWord64 e1 ^^ compile_exp_as env ae SR.Vanilla e2 ^^ - TaggedSmallWord.lsb_adjust Type.Nat8 ^^ + TaggedSmallWord.lsb_adjust Type.(if p = "regionStoreNat8" then Nat8 else Int8) ^^ Region.store_word8 env - | OtherPrim ("regionLoadNat16"), [e0; e1] -> + | OtherPrim (("regionLoadNat16" | "regionLoadInt16") as p), [e0; e1] -> SR.Vanilla, compile_exp_as env ae SR.Vanilla e0 ^^ compile_exp_as env ae SR.UnboxedWord64 e1 ^^ Region.load_word16 env ^^ - TaggedSmallWord.msb_adjust Type.Nat16 + TaggedSmallWord.msb_adjust Type.(if p = "regionLoadNat16" then Nat16 else Int16) - | OtherPrim ("regionStoreNat16"), [e0; e1; e2] -> + | OtherPrim (("regionStoreNat16" | "regionStoreInt16") as p), [e0; e1; e2] -> SR.unit, compile_exp_as env ae SR.Vanilla e0 ^^ compile_exp_as env ae SR.UnboxedWord64 e1 ^^ compile_exp_as env ae SR.Vanilla e2 ^^ - TaggedSmallWord.lsb_adjust Type.Nat16 ^^ + TaggedSmallWord.lsb_adjust Type.(if p = "regionStoreNat16" then Nat16 else Int16) ^^ Region.store_word16 env | OtherPrim ("regionLoadNat32" | "regionLoadInt32"), [e0; e1] -> @@ -10712,13 +10712,13 @@ and compile_prim_invocation (env : E.t) ae p es at = compile_exp_as env ae SR.UnboxedWord64 e2 ^^ Region.store_word64 env - | OtherPrim ("regionLoadFloat64"), [e0; e1] -> + | OtherPrim ("regionLoadFloat"), [e0; e1] -> SR.UnboxedFloat64, compile_exp_as env ae SR.Vanilla e0 ^^ compile_exp_as env ae SR.UnboxedWord64 e1 ^^ Region.load_float64 env - | OtherPrim ("regionStoreFloat64"), [e0; e1; e2] -> + | OtherPrim ("regionStoreFloat"), [e0; e1; e2] -> SR.unit, compile_exp_as env ae SR.Vanilla e0 ^^ compile_exp_as env ae SR.UnboxedWord64 e1 ^^ @@ -10847,55 +10847,32 @@ and compile_prim_invocation (env : E.t) ae p es at = compile_exp_as env ae SR.UnboxedWord32 e2 ^^ StableMemoryInterface.store_word32 env - | OtherPrim "stableMemoryLoadNat8", [e] -> + | OtherPrim (("stableMemoryLoadNat8" | "stableMemoryLoadInt8") as p), [e] -> SR.Vanilla, compile_exp_as env ae SR.UnboxedWord64 e ^^ StableMemoryInterface.load_word8 env ^^ - TaggedSmallWord.msb_adjust Type.Nat8 - - | OtherPrim "stableMemoryLoadInt8", [e] -> - SR.Vanilla, - compile_exp_as env ae SR.UnboxedWord64 e ^^ - StableMemoryInterface.load_word8 env - ^^ - TaggedSmallWord.msb_adjust Type.Int8 + TaggedSmallWord.msb_adjust Type.(if p = "stableMemoryLoadNat8" then Nat8 else Int8) (* Other prims, binary *) - | OtherPrim "stableMemoryStoreNat8", [e1; e2] -> - SR.unit, - compile_exp_as env ae SR.UnboxedWord64 e1 ^^ - compile_exp_as env ae SR.Vanilla e2 ^^ TaggedSmallWord.lsb_adjust Type.Nat8 ^^ - StableMemoryInterface.store_word8 env - - | OtherPrim "stableMemoryStoreInt8", [e1; e2] -> + | OtherPrim (("stableMemoryStoreNat8" | "stableMemoryStoreInt8") as p), [e1; e2] -> SR.unit, compile_exp_as env ae SR.UnboxedWord64 e1 ^^ - compile_exp_as env ae SR.Vanilla e2 ^^ TaggedSmallWord.lsb_adjust Type.Int8 ^^ + compile_exp_as env ae SR.Vanilla e2 ^^ + TaggedSmallWord.lsb_adjust Type.(if p = "stableMemoryStoreNat8" then Nat8 else Int8) ^^ StableMemoryInterface.store_word8 env - | OtherPrim "stableMemoryLoadNat16", [e] -> - SR.Vanilla, - compile_exp_as env ae SR.UnboxedWord64 e ^^ - StableMemoryInterface.load_word16 env ^^ - TaggedSmallWord.msb_adjust Type.Nat16 - - | OtherPrim "stableMemoryLoadInt16", [e] -> + | OtherPrim (("stableMemoryLoadNat16" | "stableMemoryLoadInt16") as p), [e] -> SR.Vanilla, compile_exp_as env ae SR.UnboxedWord64 e ^^ StableMemoryInterface.load_word16 env ^^ - TaggedSmallWord.msb_adjust Type.Int16 + TaggedSmallWord.msb_adjust Type.(if p = "stableMemoryLoadNat16" then Nat16 else Int16) - | OtherPrim "stableMemoryStoreNat16", [e1; e2] -> + | OtherPrim (("stableMemoryStoreNat16" | "stableMemoryStoreInt16") as p), [e1; e2] -> SR.unit, compile_exp_as env ae SR.UnboxedWord64 e1 ^^ - compile_exp_as env ae SR.Vanilla e2 ^^ TaggedSmallWord.lsb_adjust Type.Nat16 ^^ - StableMemoryInterface.store_word16 env - - | OtherPrim "stableMemoryStoreInt16", [e1; e2] -> - SR.unit, - compile_exp_as env ae SR.UnboxedWord64 e1 ^^ - compile_exp_as env ae SR.Vanilla e2 ^^ TaggedSmallWord.lsb_adjust Type.Int16 ^^ + compile_exp_as env ae SR.Vanilla e2 ^^ + TaggedSmallWord.lsb_adjust Type.(if p = "stableMemoryStoreNat16" then Nat16 else Int16) ^^ StableMemoryInterface.store_word16 env | OtherPrim ("stableMemoryLoadNat64" | "stableMemoryLoadInt64"), [e] -> diff --git a/test/run-drun/ok/region-test.drun-run.ok b/test/run-drun/ok/region-test.drun-run.ok new file mode 100644 index 00000000000..52c2beae4df --- /dev/null +++ b/test/run-drun/ok/region-test.drun-run.ok @@ -0,0 +1,12 @@ +ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 +debug.print: Nat8 +debug.print: Nat16 +debug.print: Nat32 +debug.print: Nat64 +debug.print: Int8 +debug.print: Int16 +debug.print: Int32 +debug.print: Int64 +debug.print: Float +debug.print: Blob +ingress Err: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: Done (rolling back changes with trap) diff --git a/test/run-drun/ok/region-test.tc.ok b/test/run-drun/ok/region-test.tc.ok new file mode 100644 index 00000000000..60fa5bd982d --- /dev/null +++ b/test/run-drun/ok/region-test.tc.ok @@ -0,0 +1,12 @@ +region-test.mo:5.5-5.6: warning [M0145], this pattern of type + Nat64 +does not cover value + 1 or 2 or _ +region-test.mo:6.5-6.7: warning [M0145], this pattern of type + Nat +does not cover value + 0 or 1 or _ +region-test.mo:7.5-7.6: warning [M0145], this pattern of type + Nat64 +does not cover value + 1 or 2 or _ diff --git a/test/run-drun/ok/stable-mem-big-blob.drun-run.ok b/test/run-drun/ok/stable-mem-big-blob.drun-run.ok index 2ba6636bfac..d0e52bea656 100644 --- a/test/run-drun/ok/stable-mem-big-blob.drun-run.ok +++ b/test/run-drun/ok/stable-mem-big-blob.drun-run.ok @@ -1,4 +1,4 @@ ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 debug.print: 255 debug.print: ok -ingress Err: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: assertion failed at stable-mem-big-blob.mo:18.3-18.15 +ingress Err: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: assertion failed at stable-mem-big-blob.mo:17.3-17.15 diff --git a/test/run-drun/ok/stable-mem-big-blob.tc.ok b/test/run-drun/ok/stable-mem-big-blob.tc.ok index 4027b6c4e61..b626baec234 100644 --- a/test/run-drun/ok/stable-mem-big-blob.tc.ok +++ b/test/run-drun/ok/stable-mem-big-blob.tc.ok @@ -1,4 +1,4 @@ -stable-mem-big-blob.mo:6.7-6.8: warning [M0145], this pattern of type +stable-mem-big-blob.mo:5.7-5.8: warning [M0145], this pattern of type Nat64 does not cover value 1 or 2 or _ diff --git a/test/run-drun/ok/stable-memory-test.drun-run.ok b/test/run-drun/ok/stable-memory-test.drun-run.ok new file mode 100644 index 00000000000..52c2beae4df --- /dev/null +++ b/test/run-drun/ok/stable-memory-test.drun-run.ok @@ -0,0 +1,12 @@ +ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 +debug.print: Nat8 +debug.print: Nat16 +debug.print: Nat32 +debug.print: Nat64 +debug.print: Int8 +debug.print: Int16 +debug.print: Int32 +debug.print: Int64 +debug.print: Float +debug.print: Blob +ingress Err: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: Done (rolling back changes with trap) diff --git a/test/run-drun/ok/stable-memory-test.tc.ok b/test/run-drun/ok/stable-memory-test.tc.ok new file mode 100644 index 00000000000..3a58a2d5f5d --- /dev/null +++ b/test/run-drun/ok/stable-memory-test.tc.ok @@ -0,0 +1,8 @@ +stable-memory-test.mo:4.5-4.6: warning [M0145], this pattern of type + Nat64 +does not cover value + 1 or 2 or _ +stable-memory-test.mo:5.5-5.6: warning [M0145], this pattern of type + Nat64 +does not cover value + 1 or 2 or _ diff --git a/test/run-drun/region-test.mo b/test/run-drun/region-test.mo new file mode 100644 index 00000000000..4a7b6f8d133 --- /dev/null +++ b/test/run-drun/region-test.mo @@ -0,0 +1,216 @@ +import Prim "mo:⛔"; +import Region "stable-region/Region"; + +let r = Region.new(); +let 0 = Region.size(r); +let 16 = Region.id(r); +let 0 = Region.grow(r, 4); +assert (4 == Region.size(r)); + +do { + Prim.debugPrint("Nat8"); + type T = Nat8; + let size : Nat64 = 1; + let mod : Nat64 = 256; + let load = Region.loadNat8; + let store = Region.storeNat8; + func conv(n : Nat64) : Nat8 { Prim.natToNat8(Prim.nat64ToNat(n % mod)) }; + let max = Region.size(r)*65536; + var i : Nat64 = 0; + while(i < max) { + store(r, i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(r, i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Nat16"); + type T = Nat16; + let size : Nat64 = 2; + let mod : Nat64 = 65536; + let load = Region.loadNat16; + let store = Region.storeNat16; + func conv(n : Nat64) : Nat16 { Prim.natToNat16(Prim.nat64ToNat(n % mod)) }; + let max = Region.size(r)*65536; + var i : Nat64 = 0; + while(i < max) { + store(r, i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(r, i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Nat32"); + type T = Nat32; + let size : Nat64 = 4; + let mod : Nat64 = 2**32; + let load = Region.loadNat32; + let store = Region.storeNat32; + func conv(n : Nat64) : Nat32 { Prim.natToNat32(Prim.nat64ToNat(n % mod)) }; + let max = Region.size(r)*65536; + var i : Nat64 = 0; + while(i < max) { + store(r, i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(r, i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Nat64"); + type T = Nat8; + let size : Nat64 = 8; + let load = Region.loadNat64; + let store = Region.storeNat64; + func conv(n : Nat64) : Nat64 { n }; + let max = Region.size(r)*65536; + var i : Nat64 = 0; + while(i < max) { + store(r, i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(r, i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Int8"); + type T = Int8; + let size : Nat64 = 1; + let mod : Nat64 = 256; + let load = Region.loadInt8; + let store = Region.storeInt8; + func conv(n : Nat64) : Int8 { Prim.intToInt8(Prim.nat64ToNat(n % mod) - 128) }; + let max = Region.size(r)*65536; + var i : Nat64 = 0; + while(i < max) { + store(r, i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(r, i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Int16"); + type T = Int16; + let size : Nat64 = 2; + let mod : Nat64 = 65536; + let load = Region.loadInt16; + let store = Region.storeInt16; + func conv(n : Nat64) : Int16 { Prim.intToInt16(Prim.nat64ToNat(n % mod) - 32768 )}; + let max = Region.size(r)*65536; + var i : Nat64 = 0; + while(i < max) { + store(r, i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(r, i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Int32"); + type T = Int32; + let size : Nat64 = 4; + let mod : Nat64 = 2**32; + let load = Region.loadInt32; + let store = Region.storeInt32; + func conv(n : Nat64) : Int32 { Prim.intToInt32(Prim.nat64ToNat(n % mod) - 2147483648) }; + let max = Region.size(r)*65536; + var i : Nat64 = 0; + while(i < max) { + store(r, i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(r, i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Int64"); + type T = Int8; + let size : Nat64 = 8; + let load = Region.loadInt64; + let store = Region.storeInt64; + func conv(n : Nat64) : Int64 { Prim.nat64ToInt64(n)+(-9223372036854775808) }; + let max = Region.size(r)*65536; + var i : Nat64 = 0; + while(i < max) { + store(r, i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(r, i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Float"); + type T = Int8; + let size : Nat64 = 8; + let load = Region.loadFloat; + let store = Region.storeFloat; + func conv(n : Nat64) : Float { Prim.int64ToFloat(Prim.nat64ToInt64(n)+(-9223372036854775808)) }; + let max = Region.size(r)*65536; + var i : Nat64 = 0; + while(i < max) { + store(r, i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(r, i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Blob"); + type T = Int8; + let load = Region.loadBlob; + let store = Region.storeBlob; + func conv(n : Nat64) : Blob { load(r, 0, Prim.nat64ToNat(n)) }; + let max : Nat64 = Region.size(r)*65536; + var i : Nat64 = 1; + while(i < max) { + let b = conv(i); + store(r, 0, b); + assert (b == load(r, 0, Prim.nat64ToNat(i))); + i := i * 2; + }; +}; + +Prim.trap("Done (rolling back changes with trap)"); + +//SKIP run-low +//SKIP run +//SKIP run-ir diff --git a/test/run-drun/region0-big-blob.mo b/test/run-drun/region0-big-blob.mo index a6972af5107..57ec3123afa 100644 --- a/test/run-drun/region0-big-blob.mo +++ b/test/run-drun/region0-big-blob.mo @@ -1,4 +1,4 @@ -//MOC-FLAG --stable-regions --sanity-checks +//MOC-FLAG --stable-regions import P "mo:⛔"; import StableMemory "stable-mem/StableMemory"; actor { diff --git a/test/run-drun/stable-mem-big-blob.mo b/test/run-drun/stable-mem-big-blob.mo index 9db89c50620..e505558bdfe 100644 --- a/test/run-drun/stable-mem-big-blob.mo +++ b/test/run-drun/stable-mem-big-blob.mo @@ -1,4 +1,3 @@ -//MOC-FLAG --sanity-checks import P "mo:⛔"; import StableMemory "stable-mem/StableMemory"; actor { diff --git a/test/run-drun/stable-memory-test.mo b/test/run-drun/stable-memory-test.mo new file mode 100644 index 00000000000..2a46fb9cec3 --- /dev/null +++ b/test/run-drun/stable-memory-test.mo @@ -0,0 +1,214 @@ +import Prim "mo:⛔"; +import StableMemory "stable-mem/StableMemory"; + +let 0 = StableMemory.size(); +let 0 = StableMemory.grow(4); +assert (4 == StableMemory.size()); + +do { + Prim.debugPrint("Nat8"); + type T = Nat8; + let size : Nat64 = 1; + let mod : Nat64 = 256; + let load = StableMemory.loadNat8; + let store = StableMemory.storeNat8; + func conv(n : Nat64) : Nat8 { Prim.natToNat8(Prim.nat64ToNat(n % mod)) }; + let max = StableMemory.size()*65536; + var i : Nat64 = 0; + while(i < max) { + store(i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Nat16"); + type T = Nat16; + let size : Nat64 = 2; + let mod : Nat64 = 65536; + let load = StableMemory.loadNat16; + let store = StableMemory.storeNat16; + func conv(n : Nat64) : Nat16 { Prim.natToNat16(Prim.nat64ToNat(n % mod)) }; + let max = StableMemory.size()*65536; + var i : Nat64 = 0; + while(i < max) { + store(i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Nat32"); + type T = Nat32; + let size : Nat64 = 4; + let mod : Nat64 = 2**32; + let load = StableMemory.loadNat32; + let store = StableMemory.storeNat32; + func conv(n : Nat64) : Nat32 { Prim.natToNat32(Prim.nat64ToNat(n % mod)) }; + let max = StableMemory.size()*65536; + var i : Nat64 = 0; + while(i < max) { + store(i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Nat64"); + type T = Nat8; + let size : Nat64 = 8; + let load = StableMemory.loadNat64; + let store = StableMemory.storeNat64; + func conv(n : Nat64) : Nat64 { n }; + let max = StableMemory.size()*65536; + var i : Nat64 = 0; + while(i < max) { + store(i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Int8"); + type T = Int8; + let size : Nat64 = 1; + let mod : Nat64 = 256; + let load = StableMemory.loadInt8; + let store = StableMemory.storeInt8; + func conv(n : Nat64) : Int8 { Prim.intToInt8(Prim.nat64ToNat(n % mod) - 128) }; + let max = StableMemory.size()*65536; + var i : Nat64 = 0; + while(i < max) { + store(i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Int16"); + type T = Int16; + let size : Nat64 = 2; + let mod : Nat64 = 65536; + let load = StableMemory.loadInt16; + let store = StableMemory.storeInt16; + func conv(n : Nat64) : Int16 { Prim.intToInt16(Prim.nat64ToNat(n % mod) - 32768 )}; + let max = StableMemory.size()*65536; + var i : Nat64 = 0; + while(i < max) { + store(i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Int32"); + type T = Int32; + let size : Nat64 = 4; + let mod : Nat64 = 2**32; + let load = StableMemory.loadInt32; + let store = StableMemory.storeInt32; + func conv(n : Nat64) : Int32 { Prim.intToInt32(Prim.nat64ToNat(n % mod) - 2147483648) }; + let max = StableMemory.size()*65536; + var i : Nat64 = 0; + while(i < max) { + store(i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Int64"); + type T = Int8; + let size : Nat64 = 8; + let load = StableMemory.loadInt64; + let store = StableMemory.storeInt64; + func conv(n : Nat64) : Int64 { Prim.nat64ToInt64(n)+(-9223372036854775808) }; + let max = StableMemory.size()*65536; + var i : Nat64 = 0; + while(i < max) { + store(i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Float"); + type T = Int8; + let size : Nat64 = 8; + let load = StableMemory.loadFloat; + let store = StableMemory.storeFloat; + func conv(n : Nat64) : Float { Prim.int64ToFloat(Prim.nat64ToInt64(n)+(-9223372036854775808)) }; + let max = StableMemory.size()*65536; + var i : Nat64 = 0; + while(i < max) { + store(i, conv(i)); + i += size; + }; + i := 0; + while(i < max) { + assert (conv(i) == load(i)); + i += size; + }; +}; + +do { + Prim.debugPrint("Blob"); + type T = Int8; + let load = StableMemory.loadBlob; + let store = StableMemory.storeBlob; + func conv(n : Nat64) : Blob { load(0, Prim.nat64ToNat(n)) }; + let max : Nat64 = StableMemory.size()*65536; + var i : Nat64 = 1; + while(i < max) { + let b = conv(i); + store(0, b); + assert (b == load(0, Prim.nat64ToNat(i))); + i := i * 2; + }; +}; + +Prim.trap("Done (rolling back changes with trap)"); + +//SKIP run-low +//SKIP run +//SKIP run-ir