From f0bd93d1f01f0bf56c1c78fa8a9096b65f9ede11 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 16 Jun 2025 22:56:34 +0200 Subject: [PATCH] Additional #2210 fixes. --- src/compiler/llvm_codegen_expr.c | 9 +-- .../test_suite/assert/unreachable_macro_3.c3t | 45 ++++++++++++ .../test_suite/assert/unreachable_macro_4.c3t | 24 +++++++ .../assert/unreachable_macro_fn.c3t | 69 +++++++++++++++++++ 4 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 test/test_suite/assert/unreachable_macro_3.c3t create mode 100644 test/test_suite/assert/unreachable_macro_4.c3t create mode 100644 test/test_suite/assert/unreachable_macro_fn.c3t diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 983a0ed2b..bf01a5f7e 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -6129,15 +6129,16 @@ static inline void llvm_emit_macro_block(GenContext *c, BEValue *be_value, Expr c->debug.block_stack = &updated; llvm_emit_return_block(c, be_value, expr->type, expr->macro_block.first_stmt, expr->macro_block.block_exit); - if (!c->current_block && !expr->macro_block.is_noreturn) - { - llvm_emit_block(c, llvm_basic_block_new(c, "after_macro")); - } bool is_unreachable = expr->macro_block.is_noreturn && c->current_block; if (is_unreachable) { llvm_emit_unreachable(c); } + if (!c->current_block) + { + llvm_emit_block(c, llvm_basic_block_new(c, "after_macro")); + llvm_value_set(be_value, LLVMGetPoison(llvm_get_type(c, expr->type)), expr->type); + } c->debug.block_stack = old_inline_location; } diff --git a/test/test_suite/assert/unreachable_macro_3.c3t b/test/test_suite/assert/unreachable_macro_3.c3t new file mode 100644 index 000000000..ec5365dd2 --- /dev/null +++ b/test/test_suite/assert/unreachable_macro_3.c3t @@ -0,0 +1,45 @@ +// #target: windows-x64 +module test; + +struct Window +{ + char* content; +} + +macro Window @content($content = {},) +{ + $switch: + $case $defined((char*) $content): + return { .content = $content, }; + $default: + unreachable(); + $endswitch +} + +fn void main() +{ + Window[] windows = { + @content($content: { "foo" }, + ), + }; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %windows = alloca %"Window[]", align 8 + %literal = alloca [1 x %Window], align 8 + %blockret = alloca %Window, align 8 + unreachable + +after_macro: ; No predecessors! + unreachable + +after_macro1: ; No predecessors! + store %Window poison, ptr %literal, align 8 + %0 = insertvalue %"Window[]" undef, ptr %literal, 0 + %1 = insertvalue %"Window[]" %0, i64 1, 1 + store %"Window[]" %1, ptr %windows, align 8 + ret void +} diff --git a/test/test_suite/assert/unreachable_macro_4.c3t b/test/test_suite/assert/unreachable_macro_4.c3t new file mode 100644 index 000000000..7b2e71fcc --- /dev/null +++ b/test/test_suite/assert/unreachable_macro_4.c3t @@ -0,0 +1,24 @@ +// #target: windows-x64 +module test; + +fn void main() +{ + int[] kaput = { unreachable() }; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %kaput = alloca %"int[]", align 8 + %literal = alloca [1 x i32], align 4 + %blockret = alloca i32, align 4 + unreachable + +after_macro: ; No predecessors! + store i32 poison, ptr %literal, align 4 + %0 = insertvalue %"int[]" undef, ptr %literal, 0 + %1 = insertvalue %"int[]" %0, i64 1, 1 + store %"int[]" %1, ptr %kaput, align 8 + ret void +} diff --git a/test/test_suite/assert/unreachable_macro_fn.c3t b/test/test_suite/assert/unreachable_macro_fn.c3t new file mode 100644 index 000000000..113d36c3e --- /dev/null +++ b/test/test_suite/assert/unreachable_macro_fn.c3t @@ -0,0 +1,69 @@ +// #target: windows-x64 +module test; + +macro int create_int2() { + $$unreachable(); + return 2; +} + +fn void test() +{ + int x = create_int2(); +} +macro int? create_int() +{ + $$unreachable(); + return 2; +} + +fn void tester(int x) +{ +} + +fn void tester_test() +{ + (void)tester(create_int()); +} + +fn void tester_test2() +{ + (void)tester(create_int2()); +} + +/* #expect: test.ll + +; Function Attrs: nounwind uwtable +define void @test.test() #0 { +entry: + %x = alloca i32, align 4 + %blockret = alloca i32, align 4 + unreachable + +after_macro: ; No predecessors! + store i32 poison, ptr %x, align 4 + ret void +} + +; Function Attrs: nounwind uwtable +define void @test.tester(i32 %0) #0 { +entry: + ret void +} + +; Function Attrs: nounwind uwtable +define void @test.tester_test() #0 { +entry: + %blockret = alloca i32, align 4 + unreachable +} + +; Function Attrs: nounwind uwtable +define void @test.tester_test2() #0 { +entry: + %blockret = alloca i32, align 4 + unreachable + +after_macro: ; No predecessors! + call void @test.tester(i32 poison) + ret void +} \ No newline at end of file