diff --git a/releasenotes.md b/releasenotes.md index 9c9578872..6cd37dd50 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -14,6 +14,7 @@ - Incorrect length passed to scratch buffer printf. - Casting to a bitstruct would be allowed even if the type was the wrong size. - Generic modules parameterized with constants would sometimes get the wrong parameterized module name causing conversion errors #1192. +- Duplicate emit of expressions on negation would incorrectly compile negated macros. ### Stdlib changes - Add 'zstr' variants for `string::new_format` / `string::tformat`. diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 1b80d3fe1..0172514e8 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -2694,8 +2694,6 @@ static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr) return; } assert(type->canonical != type_bool); - llvm_emit_expr(c, value, expr->unary_expr.expr); - llvm_value_rvalue(c, value); if (active_target.feature.trap_on_wrap && !type_flat_is_vector(value->type)) { LLVMValueRef zero = llvm_get_zero(c, expr->unary_expr.expr->type); diff --git a/test/test_suite/cast/top_down_casts.c3t b/test/test_suite/cast/top_down_casts.c3t index f39fa7f58..3790c1d67 100644 --- a/test/test_suite/cast/top_down_casts.c3t +++ b/test/test_suite/cast/top_down_casts.c3t @@ -73,23 +73,22 @@ entry: %sext11 = sext i32 %bnot to i64 store i64 %sext11, ptr %z, align 8 %17 = load i32, ptr %x, align 4 - %18 = load i32, ptr %x, align 4 - %neg = sub i32 0, %18 + %neg = sub i32 0, %17 %sext12 = sext i32 %neg to i64 store i64 %sext12, ptr %z, align 8 store i64 0, ptr %w.f, align 8 store i32 0, ptr %w, align 4 %optval = load i64, ptr %w.f, align 8 %not_err = icmp eq i64 %optval, 0 - %19 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) - br i1 %19, label %after_check, label %else_block + %18 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %18, label %after_check, label %else_block after_check: ; preds = %entry - %20 = load i32, ptr %w, align 4 + %19 = load i32, ptr %w, align 4 br label %phi_block else_block: ; preds = %entry br label %phi_block phi_block: ; preds = %else_block, %after_check - %val = phi i32 [ %20, %after_check ], [ 1, %else_block ] + %val = phi i32 [ %19, %after_check ], [ 1, %else_block ] %sext13 = sext i32 %val to i64 store i64 %sext13, ptr %z, align 8 ret void diff --git a/test/test_suite/expressions/negated_macro.c3t b/test/test_suite/expressions/negated_macro.c3t new file mode 100644 index 000000000..3f7e8e8b3 --- /dev/null +++ b/test/test_suite/expressions/negated_macro.c3t @@ -0,0 +1,37 @@ +// #target: macos-x64 +module test; +struct Foo +{ + int hello; + int bar; +} + +macro usz @offsetof($Type) { + $Type* x; + return x.bar; +} + + +fn void main(String[] argv) +{ + Foo x; + (Foo*)((void*)&x - @offsetof(Foo)); +} + + +/* #expect: test.ll + + +entry: + store i32 0, ptr %x, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 4 + store i32 0, ptr %ptradd1, align 4 + store ptr null, ptr %x2, align 8 + %2 = load ptr, ptr %x2, align 8 + %ptradd3 = getelementptr inbounds i8, ptr %2, i64 4 + %3 = load i32, ptr %ptradd3, align 4 + %sext = sext i32 %3 to i64 + %neg = sub i64 0, %sext + %ptradd_any = getelementptr i8, ptr %x, i64 %neg + ret void +} \ No newline at end of file diff --git a/test/test_suite/vector/vector_bit.c3t b/test/test_suite/vector/vector_bit.c3t index cb08e581a..25d8a4858 100644 --- a/test/test_suite/vector/vector_bit.c3t +++ b/test/test_suite/vector/vector_bit.c3t @@ -120,35 +120,34 @@ entry: %41 = extractelement <4 x i32> %40, i64 3 %42 = call i32 (ptr, ...) @printf(ptr @.str.4, i32 %35, i32 %37, i32 %39, i32 %41) %43 = load <4 x i32>, ptr %y, align 16 - %44 = load <4 x i32>, ptr %y, align 16 - %neg = sub <4 x i32> zeroinitializer, %44 + %neg = sub <4 x i32> zeroinitializer, %43 store <4 x i32> %neg, ptr %w, align 16 - %45 = load <4 x i32>, ptr %w, align 16 - %46 = extractelement <4 x i32> %45, i64 0 - %47 = load <4 x i32>, ptr %w, align 16 - %48 = extractelement <4 x i32> %47, i64 1 - %49 = load <4 x i32>, ptr %w, align 16 - %50 = extractelement <4 x i32> %49, i64 2 - %51 = load <4 x i32>, ptr %w, align 16 - %52 = extractelement <4 x i32> %51, i64 3 - %53 = call i32 (ptr, ...) @printf(ptr @.str.5, i32 %46, i32 %48, i32 %50, i32 %52) - %54 = load <4 x i32>, ptr %y, align 16 - %not = icmp eq <4 x i32> %54, zeroinitializer - %55 = sext <4 x i1> %not to <4 x i32> - store <4 x i32> %55, ptr %w, align 16 + %44 = load <4 x i32>, ptr %w, align 16 + %45 = extractelement <4 x i32> %44, i64 0 + %46 = load <4 x i32>, ptr %w, align 16 + %47 = extractelement <4 x i32> %46, i64 1 + %48 = load <4 x i32>, ptr %w, align 16 + %49 = extractelement <4 x i32> %48, i64 2 + %50 = load <4 x i32>, ptr %w, align 16 + %51 = extractelement <4 x i32> %50, i64 3 + %52 = call i32 (ptr, ...) @printf(ptr @.str.5, i32 %45, i32 %47, i32 %49, i32 %51) + %53 = load <4 x i32>, ptr %y, align 16 + %not = icmp eq <4 x i32> %53, zeroinitializer + %54 = sext <4 x i1> %not to <4 x i32> + store <4 x i32> %54, ptr %w, align 16 store <4 x i32> , ptr %w, align 16 - %56 = load <4 x i32>, ptr %w, align 16 - %not1 = icmp eq <4 x i32> %56, zeroinitializer - %57 = sext <4 x i1> %not1 to <4 x i32> - store <4 x i32> %57, ptr %w, align 16 - %58 = load <4 x i32>, ptr %w, align 16 - %59 = extractelement <4 x i32> %58, i64 0 - %60 = load <4 x i32>, ptr %w, align 16 - %61 = extractelement <4 x i32> %60, i64 1 - %62 = load <4 x i32>, ptr %w, align 16 - %63 = extractelement <4 x i32> %62, i64 2 - %64 = load <4 x i32>, ptr %w, align 16 - %65 = extractelement <4 x i32> %64, i64 3 - %66 = call i32 (ptr, ...) @printf(ptr @.str.6, i32 %59, i32 %61, i32 %63, i32 %65) + %55 = load <4 x i32>, ptr %w, align 16 + %not1 = icmp eq <4 x i32> %55, zeroinitializer + %56 = sext <4 x i1> %not1 to <4 x i32> + store <4 x i32> %56, ptr %w, align 16 + %57 = load <4 x i32>, ptr %w, align 16 + %58 = extractelement <4 x i32> %57, i64 0 + %59 = load <4 x i32>, ptr %w, align 16 + %60 = extractelement <4 x i32> %59, i64 1 + %61 = load <4 x i32>, ptr %w, align 16 + %62 = extractelement <4 x i32> %61, i64 2 + %63 = load <4 x i32>, ptr %w, align 16 + %64 = extractelement <4 x i32> %63, i64 3 + %65 = call i32 (ptr, ...) @printf(ptr @.str.6, i32 %58, i32 %60, i32 %62, i32 %64) ret void }