From 781c1fba0796e6bca4a217b1bcca065cc8c1080d Mon Sep 17 00:00:00 2001 From: "Ben L. Titzer" Date: Thu, 21 Dec 2023 19:17:55 -0500 Subject: [PATCH] Fix mapBlockEnd bug --- aeneas/src/main/Version.v3 | 2 +- aeneas/src/ssa/SsaRebuilder.v3 | 18 +++++++--- test/core/zresult0.v3 | 63 ++++++++++++++++++++++++++++++++++ test/core/zsplit_shift0.v3 | 11 ++++++ test/core/zsplit_shift1.v3 | 20 +++++++++++ test/core/zsplit_shift2.v3 | 19 ++++++++++ test/float/ziquery_split0.v3 | 15 ++++++++ test/float/ziquery_split1.v3 | 13 +++++++ test/float/zitruncf_split1.v3 | 13 +++++++ test/gc/test.bash | 2 +- test/range/promote08.v3 | 14 ++++++++ test/range/promote09.v3 | 12 +++++++ 12 files changed, 196 insertions(+), 6 deletions(-) create mode 100644 test/core/zresult0.v3 create mode 100644 test/core/zsplit_shift0.v3 create mode 100644 test/core/zsplit_shift1.v3 create mode 100644 test/core/zsplit_shift2.v3 create mode 100644 test/float/ziquery_split0.v3 create mode 100644 test/float/ziquery_split1.v3 create mode 100644 test/float/zitruncf_split1.v3 create mode 100644 test/range/promote08.v3 create mode 100644 test/range/promote09.v3 diff --git a/aeneas/src/main/Version.v3 b/aeneas/src/main/Version.v3 index 1ae896114..d9bc32406 100644 --- a/aeneas/src/main/Version.v3 +++ b/aeneas/src/main/Version.v3 @@ -3,6 +3,6 @@ // Updated by VCS scripts. DO NOT EDIT. component Version { - def version: string = "III-7.1673"; + def version: string = "III-7.1674"; var buildData: string; } diff --git a/aeneas/src/ssa/SsaRebuilder.v3 b/aeneas/src/ssa/SsaRebuilder.v3 index 28594b9ce..65469dcb2 100644 --- a/aeneas/src/ssa/SsaRebuilder.v3 +++ b/aeneas/src/ssa/SsaRebuilder.v3 @@ -33,8 +33,11 @@ class SsaRebuilder(context: SsaContext) { context.block = ob; // XXX: is it possible to reuse the SSA builder here to save garbage? this.curBlock = SsaBuilder.new(context, newGraph, nb); + var newBlock = curBlock.block; blocks++; genInstrs(ob); + var newEndBlock = curBlock.block; + if (newEndBlock != newBlock && blockEndMap != null) blockEndMap[ob] = newEndBlock; } def genInstrs(ob: SsaBlock) { for (i = ob.next; i != ob && !curBlock.end; i = i.next) { @@ -98,9 +101,11 @@ class SsaRebuilder(context: SsaContext) { var preds = nb.preds; for (i < preds.length) { var inEdge = preds[i], pred = inEdge.src; - newPreds[i] = pred.block(); - if (pred.block().succs().length > 1) { + var pred_block = pred.block(); + newPreds[i] = pred_block; + if (pred_block.succs().length > 1) { // split critical edge between src & dest +// Terminal.put2("split critical edge #%d -> #%d\n", pred_block.uid, nb.uid); var newBlock = SsaBlock.new(); newBlock.preds = [inEdge]; inEdge.dest = newBlock; @@ -116,9 +121,14 @@ class SsaRebuilder(context: SsaContext) { for (i < oldEdges.length) { if (oldEdges[i] == null || oldEdges[i].src == null) context.fail("null input edge"); if (oldEdges[i] == null) context.fail("is null"); - var newPred = mapBlockEnd(oldEdges[i].src.block()); + var oldPred = oldEdges[i].src.block(); + var newPred = mapBlockEnd(oldPred); +// Terminal.put3(" ob.preds[%d]=#%d -> #%d\n", i, oldPred.uid, if(newPred != null, newPred.uid, -1)); for (j < newPreds.length) { - if (newPred == newPreds[j]) map[j] = i; + if (newPred == newPreds[j]) { + map[j] = i; +// Terminal.put3(" edgeMap ob[%d] -> #%d at nb[%d]\n", i, newPred.uid, j); + } } } if (edgeMapMap == null) edgeMapMap = Ssa.newBlockMap(); diff --git a/test/core/zresult0.v3 b/test/core/zresult0.v3 new file mode 100644 index 000000000..a30a7fa0a --- /dev/null +++ b/test/core/zresult0.v3 @@ -0,0 +1,63 @@ +//@execute false=111 + +type Value { + case I32(val: u32); + case I64(val: u64); +} +class Throwable { } +class ArrayStack { + var elems = Array.new(100); +} +class WasmStack { } + +type Result2 { + case Return(vals: Range); + case Throw(thrown: Throwable); + case Suspend(stack: WasmStack, valrefs: Range); +} + +enum StackState { + EMPTY, // contains no frames + SUSPENDED, // contains one or more frames, waiting for inputs + RESUMABLE, // all inputs set; can be resumed + RUNNING, // currently running Wasm or host code + RETURNING, // used internally + THROWING, // used internally +} + +def resume(parent: WasmStack) -> Result2 { + // Set the initial state to running and loop until return, throw, or suspend. + // Return the appropriate result. + var r: Result2; + match (state_) { + THROWING => { + r = Result2.Throw(thrown); + } + RETURNING => { + var vals = values.elems[0 ... 1]; + r = Result2.Return(vals); + } + _ => { + } + } + return r; +} + +var thrown: Throwable; +var state_: StackState; +def values = ArrayStack.new(); + +def main(a: bool) -> int { + var stack: WasmStack; + if (a) { + thrown = Throwable.new(); + state_ = StackState.THROWING; + stack = WasmStack.new(); + values.elems[0] = Value.I32(11); + values.elems[1] = Value.I32(12); + values.elems[2] = Value.I64(13); + values.elems = null; + } + resume(stack); + return 111; +} \ No newline at end of file diff --git a/test/core/zsplit_shift0.v3 b/test/core/zsplit_shift0.v3 new file mode 100644 index 000000000..21b0abfe0 --- /dev/null +++ b/test/core/zsplit_shift0.v3 @@ -0,0 +1,11 @@ +//@execute -2=204797952; -1=204797952; 0=0; 1=0; 2=0 +def main(a: int) -> int { + var x = 99999; + var shift: byte = if(a < 0, 11, 33); + if (a < 0) { + x = if(a == -1, x << shift, x << shift); + } else { + x = if(a == 1, x << shift, x << shift); + } + return x; +} diff --git a/test/core/zsplit_shift1.v3 b/test/core/zsplit_shift1.v3 new file mode 100644 index 000000000..f3ff003b9 --- /dev/null +++ b/test/core/zsplit_shift1.v3 @@ -0,0 +1,20 @@ +//@execute -1=42; 0=249977; 1=499954; 2=62494; 3=976; 4=0; 5=976; 6=7811; 7=0; 8=42 +def shift(a: bool, s1: byte, s2: byte) -> int { + var x = 999909; + if (a) x = x >> s1; + else x = x >> s2; + return x; +} +def main(a: int) -> int { + match (a) { + 0 => return shift(false, 1, 2); + 1 => return shift(true, 1, 2); + 2 => return shift(false, 10, 4); + 3 => return shift(true, 10, 4); + 4 => return shift(false, 10, 44); + 5 => return shift(true, 10, 44); + 6 => return shift(false, 33, 7); + 7 => return shift(true, 33, 7); + } + return 42; +} diff --git a/test/core/zsplit_shift2.v3 b/test/core/zsplit_shift2.v3 new file mode 100644 index 000000000..854c76566 --- /dev/null +++ b/test/core/zsplit_shift2.v3 @@ -0,0 +1,19 @@ +//@execute -1=42; 0=999909; 1=499954; 2=999909; 3=976; 4=999909; 5=976; 6=999909; 7=0; 8=42 +def shift(a: bool, s1: byte, s2: byte) -> int { + var x = 999909; + if (a) x = x >> s1; + return x; +} +def main(a: int) -> int { + match (a) { + 0 => return shift(false, 1, 2); + 1 => return shift(true, 1, 2); + 2 => return shift(false, 10, 4); + 3 => return shift(true, 10, 4); + 4 => return shift(false, 10, 44); + 5 => return shift(true, 10, 44); + 6 => return shift(false, 33, 7); + 7 => return shift(true, 33, 7); + } + return 42; +} diff --git a/test/float/ziquery_split0.v3 b/test/float/ziquery_split0.v3 new file mode 100644 index 000000000..a09f2b8a6 --- /dev/null +++ b/test/float/ziquery_split0.v3 @@ -0,0 +1,15 @@ +//@execute 0=false; 1=true; 2=false; 3=false; 4=false +def split(a: bool, f: float) -> bool { + var r: bool; + if (a) r = i32.?(f); + return r; +} +def main(a: int) -> bool { + match (a) { + 0 => return split(false, 0.0f); + 1 => return split(true, 0.0f); + 2 => return split(false, 1.1f); + 3 => return split(true, 1.1f); + } + return false; +} diff --git a/test/float/ziquery_split1.v3 b/test/float/ziquery_split1.v3 new file mode 100644 index 000000000..5929010b3 --- /dev/null +++ b/test/float/ziquery_split1.v3 @@ -0,0 +1,13 @@ +//@execute 0=true; 1=true; 2=true; 3=true; 2000000000=false +def main(a: int) -> bool { + var f = float.!(a) + 1.0f; + var r: bool; + match (a) { + 0 => r = i32.?(f); + 1 => r = i31.?(f); + 2 => r = i30.?(f); + 3 => r = i29.?(f); + _ => r = i6.?(f); + } + return r; +} diff --git a/test/float/zitruncf_split1.v3 b/test/float/zitruncf_split1.v3 new file mode 100644 index 000000000..e61328863 --- /dev/null +++ b/test/float/zitruncf_split1.v3 @@ -0,0 +1,13 @@ +//@execute 0=1; 1=2; 2=3; 3=4; 2000000000=31 +def main(a: int) -> int { + var f = float.!(a) + 1.0f; + var r: int; + match (a) { + 0 => r = i32.truncf(f); + 1 => r = i31.truncf(f); + 2 => r = i30.truncf(f); + 3 => r = i29.truncf(f); + _ => r = i6.truncf(f); + } + return r; +} diff --git a/test/gc/test.bash b/test/gc/test.bash index 37ecdb57b..fe2ef910c 100755 --- a/test/gc/test.bash +++ b/test/gc/test.bash @@ -29,7 +29,7 @@ function do_int_test() { rm -f $ALL if [[ "$target" =~ "x86-64" ]]; then - HEAP='-heap-size=65m' # 64-bit needs more heap + HEAP='-heap-size=66m' # 64-bit needs more heap else HEAP='-heap-size=32m' fi diff --git a/test/range/promote08.v3 b/test/range/promote08.v3 new file mode 100644 index 000000000..4d5a7b64d --- /dev/null +++ b/test/range/promote08.v3 @@ -0,0 +1,14 @@ +//@execute -2=0; -1=4; 0=0; 1=4; 2=0 + +def x = "aabb"; +def y: Array; + +def main(a: int) -> int { + var z: Range; + if (a < 0) { + z = if(a == -1, x, y); + } else { + z = if(a == 1, x, y); + } + return z.length; +} \ No newline at end of file diff --git a/test/range/promote09.v3 b/test/range/promote09.v3 new file mode 100644 index 000000000..bc71b27e9 --- /dev/null +++ b/test/range/promote09.v3 @@ -0,0 +1,12 @@ +//@execute -2=0; -1=4; 0=0; 1=0; 2=0 + +def x = "aabb"; +def y: Array; + +def main(a: int) -> int { + var z: Range; + if (a < 0) { + z = if(a == -1, x, y); + } + return z.length; +} \ No newline at end of file