From e2734b4799c107d430665c46483a480f2ac72418 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 3 Jul 2023 23:49:34 +0200 Subject: [PATCH 01/22] add some simpler codegen tests --- test/codegen/basic0.art | 4 ++++ test/codegen/basic1.art | 9 +++++++++ test/codegen/basic2.art | 11 +++++++++++ 3 files changed, 24 insertions(+) create mode 100644 test/codegen/basic0.art create mode 100644 test/codegen/basic1.art create mode 100644 test/codegen/basic2.art diff --git a/test/codegen/basic0.art b/test/codegen/basic0.art new file mode 100644 index 00000000..e96b34e0 --- /dev/null +++ b/test/codegen/basic0.art @@ -0,0 +1,4 @@ +#[export] +fn foo(f: fn(i32) -> i32) -> i32 { + return (f(6)) +} diff --git a/test/codegen/basic1.art b/test/codegen/basic1.art new file mode 100644 index 00000000..13a3d282 --- /dev/null +++ b/test/codegen/basic1.art @@ -0,0 +1,9 @@ +#[import(cc="C")] +fn bar() -> (); + +#[export] +fn foo(f: fn(i32, fn(i32) -> ()) -> ()) -> i32 { + f(5, return); + + return (9) +} diff --git a/test/codegen/basic2.art b/test/codegen/basic2.art new file mode 100644 index 00000000..9405e42e --- /dev/null +++ b/test/codegen/basic2.art @@ -0,0 +1,11 @@ +#[import(cc="C")] +fn bar() -> (); + +#[export] +fn foo(f: fn(i32) -> i32) -> i32 { + while true { + if (f(5) > 6) { break() } + } + + return (9) +} From 6318d92089705456686355a114d276226d8514b0 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 4 Jul 2023 00:07:48 +0200 Subject: [PATCH 02/22] temporarily allow higher-order fn interfaces --- src/check.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/check.cpp b/src/check.cpp index 4efbe2a2..5bfb3b4b 100644 --- a/src/check.cpp +++ b/src/check.cpp @@ -761,8 +761,8 @@ void NamedAttr::check(TypeChecker& checker, const ast::Node* node) { auto fn_type = fn_decl->type->isa(); if (!fn_type) checker.error(fn_decl->loc, "polymorphic functions cannot be exported"); - else if (fn_decl->type->order() > 1) - checker.error(fn_decl->loc, "higher-order functions cannot be exported"); + //else if (fn_decl->type->order() > 1) + // checker.error(fn_decl->loc, "higher-order functions cannot be exported"); else if (!fn_decl->fn->body) checker.error(fn_decl->loc, "exported functions must have a body"); else From a21c80479d6d0138c7c36e82e6461d5df314bf26 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 4 Jul 2023 17:55:02 +0200 Subject: [PATCH 03/22] added mutually recursive closures test --- test/codegen/basic3.art | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 test/codegen/basic3.art diff --git a/test/codegen/basic3.art b/test/codegen/basic3.art new file mode 100644 index 00000000..c2820dae --- /dev/null +++ b/test/codegen/basic3.art @@ -0,0 +1,18 @@ +#[import(cc="C")] +fn leak(fn(i32) -> i32) -> (); + +#[export] +fn foo(i: i32) -> i32 { + fn f(x: i32) -> i32 { + fn g(y: i32) -> i32 { + f(x + y + i) + } + + leak(g); + g(x) + } + + leak(f); + + 0 +} From 283e18104aacca8ef176d988339b92b01eafecce Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 6 Jul 2023 15:43:24 +0200 Subject: [PATCH 04/22] improved closure conversion tests --- test/CMakeLists.txt | 6 ++++++ test/codegen/basic0.art | 4 ---- test/thorin/closure_conv_allocated_env.art | 12 ++++++++++++ .../basic1.art => thorin/closure_conv_capture1.art} | 3 ++- .../basic2.art => thorin/closure_conv_capture2.art} | 3 ++- test/thorin/closure_conv_no_op.art | 5 +++++ .../basic3.art => thorin/closure_conv_rec.art} | 3 +++ test/thorin/closure_conv_thin_env.art | 11 +++++++++++ 8 files changed, 41 insertions(+), 6 deletions(-) delete mode 100644 test/codegen/basic0.art create mode 100644 test/thorin/closure_conv_allocated_env.art rename test/{codegen/basic1.art => thorin/closure_conv_capture1.art} (68%) rename test/{codegen/basic2.art => thorin/closure_conv_capture2.art} (64%) create mode 100644 test/thorin/closure_conv_no_op.art rename test/{codegen/basic3.art => thorin/closure_conv_rec.art} (57%) create mode 100644 test/thorin/closure_conv_thin_env.art diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 57fcc34e..d8b7cfff 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -83,6 +83,12 @@ add_test(NAME simple_compare COMMAND artic --print-ast ${CMAKE_CURRENT_SOURC add_test(NAME simple_double_ptr COMMAND artic --print-ast ${CMAKE_CURRENT_SOURCE_DIR}/simple/double_ptr.art) add_test(NAME simple_math COMMAND artic --print-ast ${CMAKE_CURRENT_SOURCE_DIR}/simple/math.art) +add_test(NAME closure_conv_no_op COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_no_op.art) +add_test(NAME closure_conv_thin_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_thin_env.art) +add_test(NAME closure_conv_allocated_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_allocated_env.art) +add_test(NAME closure_conv_capture1 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture1.art) +add_test(NAME closure_conv_capture2 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture2.art) + add_failure_test(NAME failure_annot COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/annot.art) add_failure_test(NAME failure_comment COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/comment.art) add_failure_test(NAME failure_utf8 COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/utf8.art) diff --git a/test/codegen/basic0.art b/test/codegen/basic0.art deleted file mode 100644 index e96b34e0..00000000 --- a/test/codegen/basic0.art +++ /dev/null @@ -1,4 +0,0 @@ -#[export] -fn foo(f: fn(i32) -> i32) -> i32 { - return (f(6)) -} diff --git a/test/thorin/closure_conv_allocated_env.art b/test/thorin/closure_conv_allocated_env.art new file mode 100644 index 00000000..9f912156 --- /dev/null +++ b/test/thorin/closure_conv_allocated_env.art @@ -0,0 +1,12 @@ +#[import(cc="C")] +fn leak(fn(i32) -> (i32, i32)) -> (); + +// this time the environment is too big to fit in a pointer and must be allocated/extracted from +#[export] +fn foo(x: i32, z: i32) -> i32 { + fn f(y: i32) { (x + y, z) } + + leak(f); + + return (0) +} diff --git a/test/codegen/basic1.art b/test/thorin/closure_conv_capture1.art similarity index 68% rename from test/codegen/basic1.art rename to test/thorin/closure_conv_capture1.art index 13a3d282..407b0a5c 100644 --- a/test/codegen/basic1.art +++ b/test/thorin/closure_conv_capture1.art @@ -1,9 +1,10 @@ #[import(cc="C")] fn bar() -> (); +// we capture the return continuation of foo here #[export] fn foo(f: fn(i32, fn(i32) -> ()) -> ()) -> i32 { f(5, return); - return (9) + 0 } diff --git a/test/codegen/basic2.art b/test/thorin/closure_conv_capture2.art similarity index 64% rename from test/codegen/basic2.art rename to test/thorin/closure_conv_capture2.art index 9405e42e..279b36f0 100644 --- a/test/codegen/basic2.art +++ b/test/thorin/closure_conv_capture2.art @@ -1,11 +1,12 @@ #[import(cc="C")] fn bar() -> (); +// similar to the last one but now we capture a 'break' continuation #[export] fn foo(f: fn(i32) -> i32) -> i32 { while true { if (f(5) > 6) { break() } } - return (9) + 0 } diff --git a/test/thorin/closure_conv_no_op.art b/test/thorin/closure_conv_no_op.art new file mode 100644 index 00000000..5f847b3d --- /dev/null +++ b/test/thorin/closure_conv_no_op.art @@ -0,0 +1,5 @@ +// no actual closure conversion takes place, but the type of 'f' should be affected +#[export] +fn foo(f: fn(i32) -> i32) -> i32 { + f(42) +} diff --git a/test/codegen/basic3.art b/test/thorin/closure_conv_rec.art similarity index 57% rename from test/codegen/basic3.art rename to test/thorin/closure_conv_rec.art index c2820dae..9b07b59a 100644 --- a/test/codegen/basic3.art +++ b/test/thorin/closure_conv_rec.art @@ -1,6 +1,9 @@ #[import(cc="C")] fn leak(fn(i32) -> i32) -> (); +// we have two closures who can call each other +// this requires the closure for g to consume f's "self" parameter +// otherwise closure conversion just diverges #[export] fn foo(i: i32) -> i32 { fn f(x: i32) -> i32 { diff --git a/test/thorin/closure_conv_thin_env.art b/test/thorin/closure_conv_thin_env.art new file mode 100644 index 00000000..979594a0 --- /dev/null +++ b/test/thorin/closure_conv_thin_env.art @@ -0,0 +1,11 @@ +#[import(cc="C")] +fn leak(fn(i32) -> i32) -> (); + +#[export] +fn foo(x: i32) -> i32 { + fn f(y: i32) { x + y } + + leak(f); + + return (0) +} From 072b50b996208841324a1fec432da232ef270559 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 9 Jul 2023 13:07:54 +0200 Subject: [PATCH 05/22] added more closure conversion tests --- test/CMakeLists.txt | 2 ++ test/thorin/closure_conv_capture_bb.art | 11 +++++++++++ test/thorin/closure_conv_empty_env.art | 11 +++++++++++ 3 files changed, 24 insertions(+) create mode 100644 test/thorin/closure_conv_capture_bb.art create mode 100644 test/thorin/closure_conv_empty_env.art diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d8b7cfff..d0a1beb4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -84,10 +84,12 @@ add_test(NAME simple_double_ptr COMMAND artic --print-ast ${CMAKE_CURRENT_SOURC add_test(NAME simple_math COMMAND artic --print-ast ${CMAKE_CURRENT_SOURCE_DIR}/simple/math.art) add_test(NAME closure_conv_no_op COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_no_op.art) +add_test(NAME closure_conv_empty_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_empty_env.art) add_test(NAME closure_conv_thin_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_thin_env.art) add_test(NAME closure_conv_allocated_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_allocated_env.art) add_test(NAME closure_conv_capture1 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture1.art) add_test(NAME closure_conv_capture2 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture2.art) +add_test(NAME closure_conv_capture_bb COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_bb.art) add_failure_test(NAME failure_annot COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/annot.art) add_failure_test(NAME failure_comment COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/comment.art) diff --git a/test/thorin/closure_conv_capture_bb.art b/test/thorin/closure_conv_capture_bb.art new file mode 100644 index 00000000..3c446b5f --- /dev/null +++ b/test/thorin/closure_conv_capture_bb.art @@ -0,0 +1,11 @@ +#[import(cc="C")] +fn leak(fn(i32) -> i32) -> (); + +#[export] +fn foo(x: i32) -> i32 { + fn f(y: i32) { x } + + leak(f); + + return (0) +} diff --git a/test/thorin/closure_conv_empty_env.art b/test/thorin/closure_conv_empty_env.art new file mode 100644 index 00000000..3c446b5f --- /dev/null +++ b/test/thorin/closure_conv_empty_env.art @@ -0,0 +1,11 @@ +#[import(cc="C")] +fn leak(fn(i32) -> i32) -> (); + +#[export] +fn foo(x: i32) -> i32 { + fn f(y: i32) { x } + + leak(f); + + return (0) +} From 9c64633553fd2c822d3c786a851a4045a27a1ad9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sun, 9 Jul 2023 18:40:37 +0200 Subject: [PATCH 06/22] added another closure test --- test/CMakeLists.txt | 15 ++++++++------- test/thorin/closure_conv_capture_top_level.art | 11 +++++++++++ 2 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 test/thorin/closure_conv_capture_top_level.art diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d0a1beb4..443c780b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -83,13 +83,14 @@ add_test(NAME simple_compare COMMAND artic --print-ast ${CMAKE_CURRENT_SOURC add_test(NAME simple_double_ptr COMMAND artic --print-ast ${CMAKE_CURRENT_SOURCE_DIR}/simple/double_ptr.art) add_test(NAME simple_math COMMAND artic --print-ast ${CMAKE_CURRENT_SOURCE_DIR}/simple/math.art) -add_test(NAME closure_conv_no_op COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_no_op.art) -add_test(NAME closure_conv_empty_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_empty_env.art) -add_test(NAME closure_conv_thin_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_thin_env.art) -add_test(NAME closure_conv_allocated_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_allocated_env.art) -add_test(NAME closure_conv_capture1 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture1.art) -add_test(NAME closure_conv_capture2 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture2.art) -add_test(NAME closure_conv_capture_bb COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_bb.art) +add_test(NAME closure_conv_no_op COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_no_op.art) +add_test(NAME closure_conv_empty_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_empty_env.art) +add_test(NAME closure_conv_thin_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_thin_env.art) +add_test(NAME closure_conv_allocated_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_allocated_env.art) +add_test(NAME closure_conv_capture1 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture1.art) +add_test(NAME closure_conv_capture2 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture2.art) +add_test(NAME closure_conv_capture_bb COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_bb.art) +add_test(NAME closure_conv_capture_top_level COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_top_level.art) add_failure_test(NAME failure_annot COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/annot.art) add_failure_test(NAME failure_comment COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/comment.art) diff --git a/test/thorin/closure_conv_capture_top_level.art b/test/thorin/closure_conv_capture_top_level.art new file mode 100644 index 00000000..8f26709e --- /dev/null +++ b/test/thorin/closure_conv_capture_top_level.art @@ -0,0 +1,11 @@ +#[import(cc="C")] +fn leak(fn(i32) -> i32) -> (); + +#[export] +fn foo(x: i32) -> i32 { + fn f(y: i32) { 0 } + + leak(f); + + return (0) +} From e74c3b59bc494ba27a2464ea8f7bfdd836d823ba Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 17 Jul 2023 11:11:38 +0200 Subject: [PATCH 07/22] added nested fn test --- test/thorin/nested_fn1.art | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 test/thorin/nested_fn1.art diff --git a/test/thorin/nested_fn1.art b/test/thorin/nested_fn1.art new file mode 100644 index 00000000..3a475695 --- /dev/null +++ b/test/thorin/nested_fn1.art @@ -0,0 +1,21 @@ +#[import(cc="C")] +fn out(i32) -> (); + +#[export] +fn foo(mut i: i32) -> i32 { + fn f(mut x: i32) -> i32 { + if (x == i) { + x *= 3; + } + out(x); + x * 3 + } + + f(i); + + i += 1; + + f(i); + + 0 +} From f090d1bb66bc66e458999f1c68025a95bc267a2e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 17 Jul 2023 20:46:36 +0200 Subject: [PATCH 08/22] added more tests --- test/thorin/closure_conv_capture1.art | 12 ++++++++---- test/thorin/closure_conv_capture2.art | 9 ++++----- test/thorin/closure_conv_capture3.art | 18 ++++++++++++++++++ test/thorin/closure_conv_capture4.art | 16 ++++++++++++++++ test/thorin/lift_non_inlineable_loop.art | 20 ++++++++++++++++++++ test/thorin/lift_range_body.art | 18 ++++++++++++++++++ test/thorin/lift_two_ranges.art | 24 ++++++++++++++++++++++++ test/thorin/test.art | 18 ++++++++++++++++++ 8 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 test/thorin/closure_conv_capture3.art create mode 100644 test/thorin/closure_conv_capture4.art create mode 100644 test/thorin/lift_non_inlineable_loop.art create mode 100644 test/thorin/lift_range_body.art create mode 100644 test/thorin/lift_two_ranges.art create mode 100644 test/thorin/test.art diff --git a/test/thorin/closure_conv_capture1.art b/test/thorin/closure_conv_capture1.art index 407b0a5c..a60104a8 100644 --- a/test/thorin/closure_conv_capture1.art +++ b/test/thorin/closure_conv_capture1.art @@ -1,10 +1,14 @@ #[import(cc="C")] -fn bar() -> (); +fn leak2(i32, fn(i32) -> ()) -> (); // we capture the return continuation of foo here #[export] -fn foo(f: fn(i32, fn(i32) -> ()) -> ()) -> i32 { - f(5, return); - +fn foo() -> i32 { + leak2(5, return); 0 } + +#[export] +fn bar() { + foo(); +} diff --git a/test/thorin/closure_conv_capture2.art b/test/thorin/closure_conv_capture2.art index 279b36f0..176be07b 100644 --- a/test/thorin/closure_conv_capture2.art +++ b/test/thorin/closure_conv_capture2.art @@ -1,12 +1,11 @@ #[import(cc="C")] -fn bar() -> (); +fn leak2(i32, fn() -> ()) -> (); // similar to the last one but now we capture a 'break' continuation #[export] -fn foo(f: fn(i32) -> i32) -> i32 { +fn foo() -> i32 { while true { - if (f(5) > 6) { break() } + leak2(5, break); } - 0 -} +} \ No newline at end of file diff --git a/test/thorin/closure_conv_capture3.art b/test/thorin/closure_conv_capture3.art new file mode 100644 index 00000000..5affbdd4 --- /dev/null +++ b/test/thorin/closure_conv_capture3.art @@ -0,0 +1,18 @@ +#[import(cc="C")] +fn out(i32) -> (); + +fn bar(a: i32, b: fn() -> ()) -> () { + out(a); + b() +} + +// we capture the return continuation of foo here +#[export] +fn foo(x: i32, y: &i32) -> i32 { + while true { + //bar(5, continue); + bar(5, break); + bar(5, break); + } + x + *y +} \ No newline at end of file diff --git a/test/thorin/closure_conv_capture4.art b/test/thorin/closure_conv_capture4.art new file mode 100644 index 00000000..748c934a --- /dev/null +++ b/test/thorin/closure_conv_capture4.art @@ -0,0 +1,16 @@ +fn run(f: fn(i32) -> i32, x: i32) { + f(x) +} + +fn foo(x: i32, y: &mut i32) -> i32 { + if (x == 0) + { x + *y } + else + { 9 } +} + +#[export] +fn bar(x: i32, y: &mut i32) -> i32 { + foo(x + 1, y); + *y +} \ No newline at end of file diff --git a/test/thorin/lift_non_inlineable_loop.art b/test/thorin/lift_non_inlineable_loop.art new file mode 100644 index 00000000..000967bb --- /dev/null +++ b/test/thorin/lift_non_inlineable_loop.art @@ -0,0 +1,20 @@ +fn @range(body: fn (i32) -> ()) { + fn loop(a: i32, b: i32) -> () { + if a < b { + body(a); + loop(a + 1, b) + } + } + loop +} + +#[export] +fn foo(count: i32, buf: &mut[i32]) -> i32 { + let mut acc = 0; + fn inner(i: i32) { + acc += buf(i); + } + range(inner)(0, count); + range(inner)(0, count); + acc +} diff --git a/test/thorin/lift_range_body.art b/test/thorin/lift_range_body.art new file mode 100644 index 00000000..9a070c66 --- /dev/null +++ b/test/thorin/lift_range_body.art @@ -0,0 +1,18 @@ +fn @range(body: fn (i32) -> ()) { + fn loop(a: i32, b: i32) -> () { + if a < b { + body(a); + loop(a + 1, b) + } + } + loop +} + +#[export] +fn foo(count: i32, buf: &mut[i32]) -> i32 { + let mut acc = 0; + for i in range(0, count) { + acc += buf(i); + } + acc +} diff --git a/test/thorin/lift_two_ranges.art b/test/thorin/lift_two_ranges.art new file mode 100644 index 00000000..63784a35 --- /dev/null +++ b/test/thorin/lift_two_ranges.art @@ -0,0 +1,24 @@ +fn @range(body: fn (i32) -> ()) { + fn loop(a: i32, b: i32) -> () { + if a < b { + body(a); + loop(a + 1, b) + } + } + loop +} + +#[export] +fn foo(count: i32, buf: &mut[i32]) -> i32 { + let mut acc = 0; + let r = return; + let skip: fn() -> () = || { r(69) }; + for i in range(0, count) { + let r = buf(i); + acc += r; + if r == 0 { + skip() + } + } + acc +} diff --git a/test/thorin/test.art b/test/thorin/test.art new file mode 100644 index 00000000..8dd77dac --- /dev/null +++ b/test/thorin/test.art @@ -0,0 +1,18 @@ +#[import(cc="C")] +fn puts(&[u8]) -> i32; + +#[import(cc="C", name="printf")] +fn printfd(&[u8], i32) -> (); + +#[export] +fn leak(f: fn(i32) -> i32) -> () { + printfd("fn(7) = %d\n", f(7)); +} + +#[import(cc="C")] +fn foo(x: i32) -> i32; + +#[export] +fn main(f: fn(i32) -> i32) -> () { + foo(4); +} From e94514001ad860f59ba9485ee926bf05b4933925 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Wed, 19 Jul 2023 13:27:52 +0200 Subject: [PATCH 09/22] tests for recursive closures (nested and flat) --- test/CMakeLists.txt | 2 ++ test/thorin/closure_conv_rec.art | 2 +- test/thorin/closure_conv_rec2.art | 21 +++++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 test/thorin/closure_conv_rec2.art diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 443c780b..f0852298 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -91,6 +91,8 @@ add_test(NAME closure_conv_capture1 COMMAND artic --print-ast --emit-c add_test(NAME closure_conv_capture2 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture2.art) add_test(NAME closure_conv_capture_bb COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_bb.art) add_test(NAME closure_conv_capture_top_level COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_top_level.art) +add_test(NAME closure_conv_rec COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_rec.art) +add_test(NAME closure_conv_rec2 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_rec2.art) add_failure_test(NAME failure_annot COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/annot.art) add_failure_test(NAME failure_comment COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/comment.art) diff --git a/test/thorin/closure_conv_rec.art b/test/thorin/closure_conv_rec.art index 9b07b59a..e62e4523 100644 --- a/test/thorin/closure_conv_rec.art +++ b/test/thorin/closure_conv_rec.art @@ -1,7 +1,7 @@ #[import(cc="C")] fn leak(fn(i32) -> i32) -> (); -// we have two closures who can call each other +// we have two nested closures that can call each other // this requires the closure for g to consume f's "self" parameter // otherwise closure conversion just diverges #[export] diff --git a/test/thorin/closure_conv_rec2.art b/test/thorin/closure_conv_rec2.art new file mode 100644 index 00000000..bd548f2b --- /dev/null +++ b/test/thorin/closure_conv_rec2.art @@ -0,0 +1,21 @@ +#[import(cc="C")] +fn leak(fn(i32) -> i32) -> (); + +// we have two closures who can call each other, neither is nested in the other. +// this results in two mutually recursive closures: their environments include the other. +// this is unequivocally painful to deal with. +#[export] +fn foo(i: i32) -> i32 { + fn f(x: i32) -> i32 { + g(x * i) + } + + fn g(y: i32) -> i32 { + f(y + i) + } + + leak(f); + leak(g); + + 0 +} From c0413bed0549ffe5d124c25604be0fec23db0069 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Sat, 22 Jul 2023 13:36:05 +0200 Subject: [PATCH 10/22] added an anydsl_alloc stub to helpers.c --- test/codegen/helpers.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/codegen/helpers.c b/test/codegen/helpers.c index 4c009870..091f089b 100644 --- a/test/codegen/helpers.c +++ b/test/codegen/helpers.c @@ -75,3 +75,7 @@ void save_img(int32_t w, int32_t h, const double* img) { } free(out_row); } + +void* anydsl_alloc(int32_t dont_care, int64_t size) { + return malloc(size); +} From 5028b0044f700524c4e71b20093efe9a657ad97e Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 25 Jul 2023 17:59:56 +0200 Subject: [PATCH 11/22] added 3 tests for various loop lifting behaviours --- test/CMakeLists.txt | 3 +++ ...on_inlineable_loop.art => range_loop1.art} | 2 +- .../{lift_range_body.art => range_loop2.art} | 5 ++++- test/thorin/range_loop3.art | 21 +++++++++++++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) rename test/thorin/{lift_non_inlineable_loop.art => range_loop1.art} (92%) rename test/thorin/{lift_range_body.art => range_loop2.art} (66%) create mode 100644 test/thorin/range_loop3.art diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f0852298..27c22d81 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -93,6 +93,9 @@ add_test(NAME closure_conv_capture_bb COMMAND artic --print-ast --emit-c add_test(NAME closure_conv_capture_top_level COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_top_level.art) add_test(NAME closure_conv_rec COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_rec.art) add_test(NAME closure_conv_rec2 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_rec2.art) +add_test(NAME range_loop1 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop1.art) +add_test(NAME range_loop2 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop2.art) +add_test(NAME range_loop3 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop3.art) add_failure_test(NAME failure_annot COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/annot.art) add_failure_test(NAME failure_comment COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/comment.art) diff --git a/test/thorin/lift_non_inlineable_loop.art b/test/thorin/range_loop1.art similarity index 92% rename from test/thorin/lift_non_inlineable_loop.art rename to test/thorin/range_loop1.art index 000967bb..dc1608c7 100644 --- a/test/thorin/lift_non_inlineable_loop.art +++ b/test/thorin/range_loop1.art @@ -15,6 +15,6 @@ fn foo(count: i32, buf: &mut[i32]) -> i32 { acc += buf(i); } range(inner)(0, count); - range(inner)(0, count); acc } + diff --git a/test/thorin/lift_range_body.art b/test/thorin/range_loop2.art similarity index 66% rename from test/thorin/lift_range_body.art rename to test/thorin/range_loop2.art index 9a070c66..abd0d277 100644 --- a/test/thorin/lift_range_body.art +++ b/test/thorin/range_loop2.art @@ -11,8 +11,11 @@ fn @range(body: fn (i32) -> ()) { #[export] fn foo(count: i32, buf: &mut[i32]) -> i32 { let mut acc = 0; - for i in range(0, count) { + fn inner(i: i32) { acc += buf(i); } + range(inner)(0, count); + range(inner)(0, count); // we now use 'inner' in two places so it cannot be inlined! acc } + diff --git a/test/thorin/range_loop3.art b/test/thorin/range_loop3.art new file mode 100644 index 00000000..f14299cf --- /dev/null +++ b/test/thorin/range_loop3.art @@ -0,0 +1,21 @@ +fn @range(body: fn (i32) -> ()) { + fn loop(a: i32, b: i32) -> () { + if a < b { + body(a); + loop(a + 1, b) + } + } + loop +} + +#[export] +fn foo(count: i32, buf: &mut[i32]) -> i32 { + let mut acc = 0; + fn @inner(i: i32) { // we have marked 'inner' for PE, and after inlining 'range', we are left with first-order calls to inner, which get PE'd + acc += buf(i); + } + range(inner)(0, count); + range(inner)(0, count); + acc +} + From daa4fd1908c0925acd297ad7c5f2d1eb7f80e471 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 28 Jul 2023 16:37:34 +0200 Subject: [PATCH 12/22] added test for parallel() --- test/thorin/parallel_basic.art | 20 ++++++++++++++++++++ test/thorin/parallel_test.c | 21 +++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 test/thorin/parallel_basic.art create mode 100644 test/thorin/parallel_test.c diff --git a/test/thorin/parallel_basic.art b/test/thorin/parallel_basic.art new file mode 100644 index 00000000..224c37da --- /dev/null +++ b/test/thorin/parallel_basic.art @@ -0,0 +1,20 @@ +#[import(cc = "thorin", name = "parallel")] fn thorin_parallel(_num_threads: i32, _lower: i32, _upper: i32, _body: fn(i32) -> ()) -> (); +fn @parallel(body: fn(i32) -> ()) = @|num_threads: i32, lower: i32, upper: i32| thorin_parallel(num_threads, lower, upper, body); + +fn @range(body: fn (i32) -> ()) { + fn loop(a: i32, b: i32) -> () { + if a < b { + body(a); + loop(a + 1, b) + } + } + loop +} + +#[export] +fn parallel_test(n: i32, a: &[i32], b: &[i32], c: &mut[i32]) -> i32 { + for i in parallel(4, 0, n) { + c(i) = a(i) + b(i); + } + 0 +} \ No newline at end of file diff --git a/test/thorin/parallel_test.c b/test/thorin/parallel_test.c new file mode 100644 index 00000000..64eee651 --- /dev/null +++ b/test/thorin/parallel_test.c @@ -0,0 +1,21 @@ +#include +#include +#include + +void parallel_test(int, int*, int*, int*); + +int main(int argc, char** argv) { + int n = 4096 * 1024; // 4M elements + int* a = malloc(sizeof(int) * n); + int* b = malloc(sizeof(int) * n); + int* c = malloc(sizeof(int) * n); + for (int i = 0; i < n; i++) { + a[i] = i % 100; + b[i] = 100 - i % 100; + } + parallel_test(n, a, b, c); + for (int i = 0; i < n; i++) { + assert(c[i] == 100); + } + printf("It werks.\n"); +} \ No newline at end of file From a93ac2fc521a822a58e375153dc05eafdbeb8947 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 28 Jul 2023 16:37:55 +0200 Subject: [PATCH 13/22] added tailrec test --- test/thorin/tail_rec_elimination.art | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 test/thorin/tail_rec_elimination.art diff --git a/test/thorin/tail_rec_elimination.art b/test/thorin/tail_rec_elimination.art new file mode 100644 index 00000000..a27f14cf --- /dev/null +++ b/test/thorin/tail_rec_elimination.art @@ -0,0 +1,13 @@ +#[export] +fn pow(x: i32, y: i32) -> i32 { + return (pow_tailrec(x, y, 1)) +} + +#[export] +fn pow_tailrec(x: i32, n: i32, acc: i32) -> i32 { + if n > 1 { + pow_tailrec(x, n - 1, acc * x) + } else { + acc + } +} \ No newline at end of file From 53cc3e48b22be0640940782daf5497e97b50e676 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 31 Jul 2023 16:59:13 +0200 Subject: [PATCH 14/22] added more tests to find edge cases in lifting --- test/thorin/parallel_functions1.art | 22 ++++++++++++++++++++++ test/thorin/parallel_functions2.art | 26 ++++++++++++++++++++++++++ test/thorin/parallel_functions3.art | 25 +++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 test/thorin/parallel_functions1.art create mode 100644 test/thorin/parallel_functions2.art create mode 100644 test/thorin/parallel_functions3.art diff --git a/test/thorin/parallel_functions1.art b/test/thorin/parallel_functions1.art new file mode 100644 index 00000000..d3ccb93c --- /dev/null +++ b/test/thorin/parallel_functions1.art @@ -0,0 +1,22 @@ +#[import(cc = "thorin", name = "parallel")] fn thorin_parallel(_num_threads: i32, _lower: i32, _upper: i32, _body: fn(i32) -> ()) -> (); +fn @parallel(body: fn(i32) -> ()) = @|num_threads: i32, lower: i32, upper: i32| thorin_parallel(num_threads, lower, upper, body); + +fn mul(x: i32, y: i32) = x * y; + +fn @range(body: fn (i32) -> ()) { + fn loop(a: i32, b: i32) -> () { + if a < b { + body(a); + loop(a + 1, b) + } + } + loop +} + +#[export] +fn parallel_test(n: i32, a: &[i32], b: &[i32], c: &mut[i32]) -> i32 { + for i in parallel(4, 0, n) { + c(i) = mul(a(i), a(i)) + mul(b(i), b(i)); + } + 0 +} \ No newline at end of file diff --git a/test/thorin/parallel_functions2.art b/test/thorin/parallel_functions2.art new file mode 100644 index 00000000..f264a7c0 --- /dev/null +++ b/test/thorin/parallel_functions2.art @@ -0,0 +1,26 @@ +#[import(cc = "thorin", name = "parallel")] fn thorin_parallel(_num_threads: i32, _lower: i32, _upper: i32, _body: fn(i32) -> ()) -> (); +fn @parallel(body: fn(i32) -> ()) = @|num_threads: i32, lower: i32, upper: i32| thorin_parallel(num_threads, lower, upper, body); + +#[import(cc="C")] +fn leak(fn(i32) -> i32) -> (); + +fn @range(body: fn (i32) -> ()) { + fn loop(a: i32, b: i32) -> () { + if a < b { + body(a); + loop(a + 1, b) + } + } + loop +} + +#[export] +fn parallel_test(n: i32, a: &[i32], b: &[i32], c: &mut[i32]) -> i32 { + fn f(x: i32) = x * n; + + for i in parallel(4, 0, n) { + leak(f); + c(i) = f(a(i)) + f(b(i)); + } + 0 +} \ No newline at end of file diff --git a/test/thorin/parallel_functions3.art b/test/thorin/parallel_functions3.art new file mode 100644 index 00000000..8978f793 --- /dev/null +++ b/test/thorin/parallel_functions3.art @@ -0,0 +1,25 @@ +#[import(cc = "thorin", name = "parallel")] fn thorin_parallel(_num_threads: i32, _lower: i32, _upper: i32, _body: fn(i32) -> ()) -> (); +fn @parallel(body: fn(i32) -> ()) = @|num_threads: i32, lower: i32, upper: i32| thorin_parallel(num_threads, lower, upper, body); + +#[import(cc="C")] +fn magic() -> fn(i32) -> i32; + +fn @range(body: fn (i32) -> ()) { + fn loop(a: i32, b: i32) -> () { + if a < b { + body(a); + loop(a + 1, b) + } + } + loop +} + +#[export] +fn parallel_test(n: i32, a: &[i32], b: &[i32], c: &mut[i32]) -> i32 { + let f = magic(); + + for i in parallel(4, 0, n) { + c(i) = f(a(i)) + f(b(i)); + } + 0 +} \ No newline at end of file From ecc70f108536987e31744c3a5761c40e6b5ab8e6 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Tue, 1 Aug 2023 18:41:37 +0200 Subject: [PATCH 15/22] added some tests for the parallel intrinsic --- test/CMakeLists.txt | 4 ++++ test/thorin/closure_conv_capture4.art | 16 ---------------- test/thorin/lift_two_ranges.art | 24 ------------------------ test/thorin/nested_fn1.art | 21 --------------------- 4 files changed, 4 insertions(+), 61 deletions(-) delete mode 100644 test/thorin/closure_conv_capture4.art delete mode 100644 test/thorin/lift_two_ranges.art delete mode 100644 test/thorin/nested_fn1.art diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 27c22d81..a6571f60 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -96,6 +96,10 @@ add_test(NAME closure_conv_rec2 COMMAND artic --print-ast --emit-c add_test(NAME range_loop1 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop1.art) add_test(NAME range_loop2 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop2.art) add_test(NAME range_loop3 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop3.art) +add_test(NAME parallel_basic COMMAND artic --print-ast --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_basic.art) +add_test(NAME parallel_functions1 COMMAND artic --print-ast --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions1.art) +add_test(NAME parallel_functions2 COMMAND artic --print-ast --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions2.art) +add_test(NAME parallel_functions3 COMMAND artic --print-ast --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions3.art) add_failure_test(NAME failure_annot COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/annot.art) add_failure_test(NAME failure_comment COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/comment.art) diff --git a/test/thorin/closure_conv_capture4.art b/test/thorin/closure_conv_capture4.art deleted file mode 100644 index 748c934a..00000000 --- a/test/thorin/closure_conv_capture4.art +++ /dev/null @@ -1,16 +0,0 @@ -fn run(f: fn(i32) -> i32, x: i32) { - f(x) -} - -fn foo(x: i32, y: &mut i32) -> i32 { - if (x == 0) - { x + *y } - else - { 9 } -} - -#[export] -fn bar(x: i32, y: &mut i32) -> i32 { - foo(x + 1, y); - *y -} \ No newline at end of file diff --git a/test/thorin/lift_two_ranges.art b/test/thorin/lift_two_ranges.art deleted file mode 100644 index 63784a35..00000000 --- a/test/thorin/lift_two_ranges.art +++ /dev/null @@ -1,24 +0,0 @@ -fn @range(body: fn (i32) -> ()) { - fn loop(a: i32, b: i32) -> () { - if a < b { - body(a); - loop(a + 1, b) - } - } - loop -} - -#[export] -fn foo(count: i32, buf: &mut[i32]) -> i32 { - let mut acc = 0; - let r = return; - let skip: fn() -> () = || { r(69) }; - for i in range(0, count) { - let r = buf(i); - acc += r; - if r == 0 { - skip() - } - } - acc -} diff --git a/test/thorin/nested_fn1.art b/test/thorin/nested_fn1.art deleted file mode 100644 index 3a475695..00000000 --- a/test/thorin/nested_fn1.art +++ /dev/null @@ -1,21 +0,0 @@ -#[import(cc="C")] -fn out(i32) -> (); - -#[export] -fn foo(mut i: i32) -> i32 { - fn f(mut x: i32) -> i32 { - if (x == i) { - x *= 3; - } - out(x); - x * 3 - } - - f(i); - - i += 1; - - f(i); - - 0 -} From 1cc2860a5d0adde3d3df97b2b3847a92ab10f687 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 3 Aug 2023 16:18:23 +0200 Subject: [PATCH 16/22] added a test that reproduces broken scheduler behaviour --- test/CMakeLists.txt | 1 + test/thorin/busted_scheduler.art | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 test/thorin/busted_scheduler.art diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a6571f60..66a1f776 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -100,6 +100,7 @@ add_test(NAME parallel_basic COMMAND artic --print-ast --emit-ll add_test(NAME parallel_functions1 COMMAND artic --print-ast --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions1.art) add_test(NAME parallel_functions2 COMMAND artic --print-ast --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions2.art) add_test(NAME parallel_functions3 COMMAND artic --print-ast --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions3.art) +add_test(NAME busted_scheduler COMMAND artic --print-ast --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/busted_scheduler.art) add_failure_test(NAME failure_annot COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/annot.art) add_failure_test(NAME failure_comment COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/comment.art) diff --git a/test/thorin/busted_scheduler.art b/test/thorin/busted_scheduler.art new file mode 100644 index 00000000..713b6b5b --- /dev/null +++ b/test/thorin/busted_scheduler.art @@ -0,0 +1,26 @@ +#[import(cc="C")] +fn bar() -> i32; + +#[import(cc="C")] +fn leak(fn(i32) -> i32) -> (); + +// this breaks the scheduler on 802e2eafbbe6cd79d4bca47c9553f315bc4568ea +// (with the inlining pass disabled) +// the old early() scheduler was not able to properly cope with recursive aggregates (the closures of f and g) +// and would end up scheduling one of them before `y` is computed. +#[export] +fn foo(z: i32) { + let y = bar(); + + fn f(x: i32) -> i32 { + g(x + y) + } + + fn g(x: i32) -> i32 { + f(x + z) + } + + leak(f); + leak(g); + 0 +} \ No newline at end of file From 3890da3df2bd50d45fb8da0044f2f1b14aefade9 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 4 Sep 2023 13:17:44 +0200 Subject: [PATCH 17/22] added -g flag to tests --- test/CMakeLists.txt | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 66a1f776..596cc2cb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -83,24 +83,24 @@ add_test(NAME simple_compare COMMAND artic --print-ast ${CMAKE_CURRENT_SOURC add_test(NAME simple_double_ptr COMMAND artic --print-ast ${CMAKE_CURRENT_SOURCE_DIR}/simple/double_ptr.art) add_test(NAME simple_math COMMAND artic --print-ast ${CMAKE_CURRENT_SOURCE_DIR}/simple/math.art) -add_test(NAME closure_conv_no_op COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_no_op.art) -add_test(NAME closure_conv_empty_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_empty_env.art) -add_test(NAME closure_conv_thin_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_thin_env.art) -add_test(NAME closure_conv_allocated_env COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_allocated_env.art) -add_test(NAME closure_conv_capture1 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture1.art) -add_test(NAME closure_conv_capture2 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture2.art) -add_test(NAME closure_conv_capture_bb COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_bb.art) -add_test(NAME closure_conv_capture_top_level COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_top_level.art) -add_test(NAME closure_conv_rec COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_rec.art) -add_test(NAME closure_conv_rec2 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_rec2.art) -add_test(NAME range_loop1 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop1.art) -add_test(NAME range_loop2 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop2.art) -add_test(NAME range_loop3 COMMAND artic --print-ast --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop3.art) -add_test(NAME parallel_basic COMMAND artic --print-ast --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_basic.art) -add_test(NAME parallel_functions1 COMMAND artic --print-ast --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions1.art) -add_test(NAME parallel_functions2 COMMAND artic --print-ast --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions2.art) -add_test(NAME parallel_functions3 COMMAND artic --print-ast --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions3.art) -add_test(NAME busted_scheduler COMMAND artic --print-ast --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/busted_scheduler.art) +add_test(NAME closure_conv_no_op COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_no_op.art) +add_test(NAME closure_conv_empty_env COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_empty_env.art) +add_test(NAME closure_conv_thin_env COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_thin_env.art) +add_test(NAME closure_conv_allocated_env COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_allocated_env.art) +add_test(NAME closure_conv_capture1 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture1.art) +add_test(NAME closure_conv_capture2 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture2.art) +add_test(NAME closure_conv_capture_bb COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_bb.art) +add_test(NAME closure_conv_capture_top_level COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_top_level.art) +add_test(NAME closure_conv_rec COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_rec.art) +add_test(NAME closure_conv_rec2 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_rec2.art) +add_test(NAME range_loop1 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop1.art) +add_test(NAME range_loop2 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop2.art) +add_test(NAME range_loop3 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop3.art) +add_test(NAME parallel_basic COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_basic.art) +add_test(NAME parallel_functions1 COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions1.art) +add_test(NAME parallel_functions2 COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions2.art) +add_test(NAME parallel_functions3 COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions3.art) +add_test(NAME busted_scheduler COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/busted_scheduler.art) add_failure_test(NAME failure_annot COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/annot.art) add_failure_test(NAME failure_comment COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/comment.art) From b31104168e6366415ab70c7bcf67c0652b957dcd Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 8 Aug 2025 10:50:35 +0200 Subject: [PATCH 18/22] tests: fix some whitespace --- test/thorin/closure_conv_allocated_env.art | 2 +- test/thorin/closure_conv_rec.art | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/thorin/closure_conv_allocated_env.art b/test/thorin/closure_conv_allocated_env.art index 9f912156..5103ac14 100644 --- a/test/thorin/closure_conv_allocated_env.art +++ b/test/thorin/closure_conv_allocated_env.art @@ -7,6 +7,6 @@ fn foo(x: i32, z: i32) -> i32 { fn f(y: i32) { (x + y, z) } leak(f); - + return (0) } diff --git a/test/thorin/closure_conv_rec.art b/test/thorin/closure_conv_rec.art index e62e4523..68e35703 100644 --- a/test/thorin/closure_conv_rec.art +++ b/test/thorin/closure_conv_rec.art @@ -10,12 +10,12 @@ fn foo(i: i32) -> i32 { fn g(y: i32) -> i32 { f(x + y + i) } - + leak(g); g(x) } - + leak(f); - + 0 } From 59ebec6e0008270031c9bab554b415e8712a3491 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 8 Aug 2025 10:51:01 +0200 Subject: [PATCH 19/22] rename the 'thorin' tests to 'backend' tests --- test/thorin/CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/thorin/CMakeLists.txt b/test/thorin/CMakeLists.txt index cca78ece..533e8e62 100644 --- a/test/thorin/CMakeLists.txt +++ b/test/thorin/CMakeLists.txt @@ -8,7 +8,7 @@ macro(assign_me_bool var) endif() endmacro() -function(add_thorin_test) +function(add_backend_test) cmake_parse_arguments(test "NO_C;NO_LLVM;NO_SPIRV" "NAME;SOURCE_FILE" "ARGS" ${ARGN}) assign_me_bool(TEST_USE_C NOT ${test_NO_C}) assign_me_bool(HAS_LLVM ${Thorin_HAS_LLVM_SUPPORT}) @@ -16,7 +16,7 @@ function(add_thorin_test) assign_me_bool(HAS_SPIRV ${Thorin_HAS_SPIRV_SUPPORT}) assign_me_bool(TEST_USE_SPIRV ${HAS_SPIRV} AND NOT ${test_NO_SPIRV}) - add_test(NAME thorin_${test_NAME} COMMAND ${CMAKE_COMMAND} + add_test(NAME backend_${test_NAME} COMMAND ${CMAKE_COMMAND} -DCOMPILER=$ -DC_COMPILER=${CMAKE_C_COMPILER} -DT=${test_NAME} @@ -30,8 +30,8 @@ function(add_thorin_test) -P ${PROJECT_SOURCE_DIR}/test/thorin/oracle.cmake) endfunction() -add_thorin_test(NAME hello_world SOURCE_FILE hello_world) -add_thorin_test(NAME llvm_intrinsic SOURCE_FILE llvm_intrinsic NO_C NO_SPIRV) -add_thorin_test(NAME spirv_builtin SOURCE_FILE spirv_builtin NO_C NO_LLVM) -add_thorin_test(NAME control_flow SOURCE_FILE control_flow) -add_thorin_test(NAME slot SOURCE_FILE slot) +add_backend_test(NAME hello_world SOURCE_FILE hello_world) +add_backend_test(NAME llvm_intrinsic SOURCE_FILE llvm_intrinsic NO_C NO_SPIRV) +add_backend_test(NAME spirv_builtin SOURCE_FILE spirv_builtin NO_C NO_LLVM) +add_backend_test(NAME control_flow SOURCE_FILE control_flow) +add_backend_test(NAME slot SOURCE_FILE slot) From 264ea42016ddac640c8d05b48b4b14933ddb7a03 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 8 Aug 2025 10:51:12 +0200 Subject: [PATCH 20/22] prefix 'thorin' tests --- test/CMakeLists.txt | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 596cc2cb..bf317d2d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -83,24 +83,24 @@ add_test(NAME simple_compare COMMAND artic --print-ast ${CMAKE_CURRENT_SOURC add_test(NAME simple_double_ptr COMMAND artic --print-ast ${CMAKE_CURRENT_SOURCE_DIR}/simple/double_ptr.art) add_test(NAME simple_math COMMAND artic --print-ast ${CMAKE_CURRENT_SOURCE_DIR}/simple/math.art) -add_test(NAME closure_conv_no_op COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_no_op.art) -add_test(NAME closure_conv_empty_env COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_empty_env.art) -add_test(NAME closure_conv_thin_env COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_thin_env.art) -add_test(NAME closure_conv_allocated_env COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_allocated_env.art) -add_test(NAME closure_conv_capture1 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture1.art) -add_test(NAME closure_conv_capture2 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture2.art) -add_test(NAME closure_conv_capture_bb COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_bb.art) -add_test(NAME closure_conv_capture_top_level COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_top_level.art) -add_test(NAME closure_conv_rec COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_rec.art) -add_test(NAME closure_conv_rec2 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_rec2.art) -add_test(NAME range_loop1 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop1.art) -add_test(NAME range_loop2 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop2.art) -add_test(NAME range_loop3 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop3.art) -add_test(NAME parallel_basic COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_basic.art) -add_test(NAME parallel_functions1 COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions1.art) -add_test(NAME parallel_functions2 COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions2.art) -add_test(NAME parallel_functions3 COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions3.art) -add_test(NAME busted_scheduler COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/busted_scheduler.art) +add_test(NAME thorin_closure_conv_no_op COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_no_op.art) +add_test(NAME thorin_closure_conv_empty_env COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_empty_env.art) +add_test(NAME thorin_closure_conv_thin_env COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_thin_env.art) +add_test(NAME thorin_closure_conv_allocated_env COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_allocated_env.art) +add_test(NAME thorin_closure_conv_capture1 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture1.art) +add_test(NAME thorin_closure_conv_capture2 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture2.art) +add_test(NAME thorin_closure_conv_capture_bb COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_bb.art) +add_test(NAME thorin_closure_conv_capture_top_level COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_capture_top_level.art) +add_test(NAME thorin_closure_conv_rec COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_rec.art) +add_test(NAME thorin_closure_conv_rec2 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/closure_conv_rec2.art) +add_test(NAME thorin_range_loop1 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop1.art) +add_test(NAME thorin_range_loop2 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop2.art) +add_test(NAME thorin_range_loop3 COMMAND artic --print-ast -g --emit-c ${CMAKE_CURRENT_SOURCE_DIR}/thorin/range_loop3.art) +add_test(NAME thorin_parallel_basic COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_basic.art) +add_test(NAME thorin_parallel_functions1 COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions1.art) +add_test(NAME thorin_parallel_functions2 COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions2.art) +add_test(NAME thorin_parallel_functions3 COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/parallel_functions3.art) +add_test(NAME thorin_busted_scheduler COMMAND artic --print-ast -g --emit-llvm ${CMAKE_CURRENT_SOURCE_DIR}/thorin/busted_scheduler.art) add_failure_test(NAME failure_annot COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/annot.art) add_failure_test(NAME failure_comment COMMAND artic ${CMAKE_CURRENT_SOURCE_DIR}/failure/comment.art) From 1ed0690362d8aae3d84889637db65337369b2764 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Fri, 8 Aug 2025 10:57:00 +0200 Subject: [PATCH 21/22] cleaned up lifting tests --- test/thorin/parallel_basic.art | 10 ---------- test/thorin/parallel_functions1.art | 10 ---------- test/thorin/parallel_functions2.art | 11 +---------- test/thorin/parallel_functions3.art | 11 +---------- 4 files changed, 2 insertions(+), 40 deletions(-) diff --git a/test/thorin/parallel_basic.art b/test/thorin/parallel_basic.art index 224c37da..9a340d21 100644 --- a/test/thorin/parallel_basic.art +++ b/test/thorin/parallel_basic.art @@ -1,16 +1,6 @@ #[import(cc = "thorin", name = "parallel")] fn thorin_parallel(_num_threads: i32, _lower: i32, _upper: i32, _body: fn(i32) -> ()) -> (); fn @parallel(body: fn(i32) -> ()) = @|num_threads: i32, lower: i32, upper: i32| thorin_parallel(num_threads, lower, upper, body); -fn @range(body: fn (i32) -> ()) { - fn loop(a: i32, b: i32) -> () { - if a < b { - body(a); - loop(a + 1, b) - } - } - loop -} - #[export] fn parallel_test(n: i32, a: &[i32], b: &[i32], c: &mut[i32]) -> i32 { for i in parallel(4, 0, n) { diff --git a/test/thorin/parallel_functions1.art b/test/thorin/parallel_functions1.art index d3ccb93c..8c573728 100644 --- a/test/thorin/parallel_functions1.art +++ b/test/thorin/parallel_functions1.art @@ -3,16 +3,6 @@ fn @parallel(body: fn(i32) -> ()) = @|num_threads: i32, lower: i32, upper: i32| fn mul(x: i32, y: i32) = x * y; -fn @range(body: fn (i32) -> ()) { - fn loop(a: i32, b: i32) -> () { - if a < b { - body(a); - loop(a + 1, b) - } - } - loop -} - #[export] fn parallel_test(n: i32, a: &[i32], b: &[i32], c: &mut[i32]) -> i32 { for i in parallel(4, 0, n) { diff --git a/test/thorin/parallel_functions2.art b/test/thorin/parallel_functions2.art index f264a7c0..bd72cc1c 100644 --- a/test/thorin/parallel_functions2.art +++ b/test/thorin/parallel_functions2.art @@ -4,21 +4,12 @@ fn @parallel(body: fn(i32) -> ()) = @|num_threads: i32, lower: i32, upper: i32| #[import(cc="C")] fn leak(fn(i32) -> i32) -> (); -fn @range(body: fn (i32) -> ()) { - fn loop(a: i32, b: i32) -> () { - if a < b { - body(a); - loop(a + 1, b) - } - } - loop -} - #[export] fn parallel_test(n: i32, a: &[i32], b: &[i32], c: &mut[i32]) -> i32 { fn f(x: i32) = x * n; for i in parallel(4, 0, n) { + // this requires lifting the local continuation 'f' leak(f); c(i) = f(a(i)) + f(b(i)); } diff --git a/test/thorin/parallel_functions3.art b/test/thorin/parallel_functions3.art index 8978f793..56dbc522 100644 --- a/test/thorin/parallel_functions3.art +++ b/test/thorin/parallel_functions3.art @@ -4,18 +4,9 @@ fn @parallel(body: fn(i32) -> ()) = @|num_threads: i32, lower: i32, upper: i32| #[import(cc="C")] fn magic() -> fn(i32) -> i32; -fn @range(body: fn (i32) -> ()) { - fn loop(a: i32, b: i32) -> () { - if a < b { - body(a); - loop(a + 1, b) - } - } - loop -} - #[export] fn parallel_test(n: i32, a: &[i32], b: &[i32], c: &mut[i32]) -> i32 { + // this produces a function pointer, it should be spillable without CC let f = magic(); for i in parallel(4, 0, n) { From 7598d769330136e6275ced7e031d757a41062479 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 14 Aug 2025 11:24:53 +0200 Subject: [PATCH 22/22] updated CC tests --- test/thorin/closure_conv_capture1.art | 7 +------ test/thorin/closure_conv_capture2.art | 4 +++- test/thorin/closure_conv_capture_bb.art | 13 +++++++++++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/test/thorin/closure_conv_capture1.art b/test/thorin/closure_conv_capture1.art index a60104a8..e85006af 100644 --- a/test/thorin/closure_conv_capture1.art +++ b/test/thorin/closure_conv_capture1.art @@ -1,5 +1,5 @@ #[import(cc="C")] -fn leak2(i32, fn(i32) -> ()) -> (); +fn leak2(i32, fn(i32) -> !) -> (); // we capture the return continuation of foo here #[export] @@ -7,8 +7,3 @@ fn foo() -> i32 { leak2(5, return); 0 } - -#[export] -fn bar() { - foo(); -} diff --git a/test/thorin/closure_conv_capture2.art b/test/thorin/closure_conv_capture2.art index 176be07b..89549bad 100644 --- a/test/thorin/closure_conv_capture2.art +++ b/test/thorin/closure_conv_capture2.art @@ -1,5 +1,5 @@ #[import(cc="C")] -fn leak2(i32, fn() -> ()) -> (); +fn leak2(i32, fn() -> !) -> (); // similar to the last one but now we capture a 'break' continuation #[export] @@ -7,5 +7,7 @@ fn foo() -> i32 { while true { leak2(5, break); } + // this basic block is unreachable from the CFG + // but should still be emitted as part of this foo's scope 0 } \ No newline at end of file diff --git a/test/thorin/closure_conv_capture_bb.art b/test/thorin/closure_conv_capture_bb.art index 3c446b5f..95fa28b0 100644 --- a/test/thorin/closure_conv_capture_bb.art +++ b/test/thorin/closure_conv_capture_bb.art @@ -1,9 +1,18 @@ #[import(cc="C")] -fn leak(fn(i32) -> i32) -> (); +fn leak(fn(i32) -> !) -> (); #[export] fn foo(x: i32) -> i32 { - fn f(y: i32) { x } + let r = return; + + // 'f' is a basic block within 'foo' + fn f(y: i32) -> ! { + if (x + y > 0) { + r(0) + } else { + r(y) + } + } leak(f);