From 3ce15bd7afbfcfe67cef3c8b0a615215d7d38753 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sun, 15 Jun 2025 22:35:44 +0200 Subject: [PATCH] Incorrect codegen if a macro ends with unreachable and is assigned to something. #2210 --- releasenotes.md | 1 + src/compiler/llvm_codegen_expr.c | 4 +- .../assert/unreachable_in_assign.c3t | 37 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 test/test_suite/assert/unreachable_in_assign.c3t diff --git a/releasenotes.md b/releasenotes.md index 967337a03..ce7d82c8d 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -40,6 +40,7 @@ - Fix to `is_array_or_slice_of_char` #2214. - Method on array slice caused segfault #2211. - In some cases, the compiler would dereference a compile time null. #2215 +- Incorrect codegen if a macro ends with unreachable and is assigned to something. #2210 ### Stdlib changes - Deprecate `String.is_zstr` and `String.quick_zstr` #2188. diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 694ade6cb..983a0ed2b 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -122,6 +122,7 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue BEValue result; // Emit the fault type. llvm_emit_expr(c, &result, expr->inner_expr); + llvm_value_rvalue(c, &result); LLVMValueRef err_val = result.value; @@ -201,7 +202,7 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue { llvm_emit_expr(c, &value, expr); } - + if (!c->current_block) goto AFTER_STORE; if (value.type != type_void) llvm_store(c, ref, &value); } @@ -209,6 +210,7 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue { llvm_store_to_ptr_raw(c, optional, llvm_get_zero(c, type_fault), type_fault); } +AFTER_STORE:; POP_CATCH(); if (assign_block) diff --git a/test/test_suite/assert/unreachable_in_assign.c3t b/test/test_suite/assert/unreachable_in_assign.c3t new file mode 100644 index 000000000..937a6d766 --- /dev/null +++ b/test/test_suite/assert/unreachable_in_assign.c3t @@ -0,0 +1,37 @@ +// #target: windows-x64 +module test; + +macro int create_int2() { + $$unreachable(); +} + +fn void test() +{ + int x = create_int2(); +} +macro int? create_int() +{ + $$unreachable(); +} + +fn int main() +{ + int? x = create_int(); +} + +/* #expect: test.ll + +define void @test.test() #0 { +entry: + %x = alloca i32, align 4 + %blockret = alloca i32, align 4 + unreachable +} + +define i32 @main() #0 { +entry: + %x = alloca i32, align 4 + %x.f = alloca i64, align 8 + %blockret = alloca i32, align 4 + unreachable +} \ No newline at end of file