From cf0405930eb9539b249efeef89878fd7e7d4d47c Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Wed, 5 Mar 2025 01:58:07 +0100 Subject: [PATCH] Fix case where occasionally atomic_load would miscompile. --- resources/examples/raylib/raylib_arkanoid.c3 | 3 +-- src/compiler/llvm_codegen_builtins.c | 10 ++++++---- src/compiler/llvm_codegen_expr.c | 2 ++ src/compiler/llvm_codegen_internal.h | 2 +- src/compiler/llvm_codegen_storeload.c | 5 +++-- test/test_suite7/macros/vasplat_function_call.c3 | 0 6 files changed, 13 insertions(+), 9 deletions(-) delete mode 100644 test/test_suite7/macros/vasplat_function_call.c3 diff --git a/resources/examples/raylib/raylib_arkanoid.c3 b/resources/examples/raylib/raylib_arkanoid.c3 index 069e3cb46..eec52c1d1 100644 --- a/resources/examples/raylib/raylib_arkanoid.c3 +++ b/resources/examples/raylib/raylib_arkanoid.c3 @@ -182,8 +182,7 @@ fn void update_game() } // Collision logic: ball vs player - if (rl::checkCollisionCircleRec(ball.position, ball.radius, - Rectangle{ player.position.x - player.size.x / 2, player.position.y - player.size.y / 2, player.size.x, player.size.y})) + if (rl::checkCollisionCircleRec(ball.position, ball.radius, { player.position.x - player.size.x / 2, player.position.y - player.size.y / 2, player.size.x, player.size.y})) { if (ball.speed.y > 0) { diff --git a/src/compiler/llvm_codegen_builtins.c b/src/compiler/llvm_codegen_builtins.c index 2469c9aa2..6e7831705 100644 --- a/src/compiler/llvm_codegen_builtins.c +++ b/src/compiler/llvm_codegen_builtins.c @@ -108,7 +108,7 @@ INLINE void llvm_emit_compare_exchange(GenContext *c, BEValue *result_value, Exp ordering_to_llvm(success_ordering), ordering_to_llvm(failure_ordering), false); if (alignment && alignment >= type_abi_alignment(type)) { - ASSERT(is_power_of_two(alignment)); + ASSERT_SPAN(expr, is_power_of_two(alignment)); LLVMSetAlignment(result, alignment); } if (is_volatile) LLVMSetVolatile(result, true); @@ -235,10 +235,12 @@ INLINE void llvm_emit_atomic_fetch(GenContext *c, BuiltinFunction func, BEValue INLINE void llvm_emit_atomic_load(GenContext *c, BEValue *result_value, Expr *expr) { llvm_emit_expr(c, result_value, expr->call_expr.arguments[0]); - llvm_value_deref(c, result_value); llvm_value_rvalue(c, result_value); - if (expr->call_expr.arguments[1]->const_expr.b) LLVMSetVolatile(result_value->value, true); - LLVMSetOrdering(result_value->value, llvm_atomic_ordering(expr->call_expr.arguments[2]->const_expr.ixx.i.low)); + Type *type = result_value->type->pointer; + LLVMValueRef val = llvm_load(c, llvm_get_type(c, type), result_value->value, type_abi_alignment(type), ""); + if (expr->call_expr.arguments[1]->const_expr.b) LLVMSetVolatile(val, true); + LLVMSetOrdering(val, llvm_atomic_ordering(expr->call_expr.arguments[2]->const_expr.ixx.i.low)); + llvm_value_set(result_value, val, type); } INLINE void llvm_emit_unaligned_load(GenContext *c, BEValue *result_value, Expr *expr) diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 01434e812..c8f024f0a 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -3064,6 +3064,8 @@ void llvm_emit_int_comp_raw(GenContext *c, BEValue *result, Type *lhs_type, Type } } } + ASSERT(LLVMTypeOf(lhs_value) == LLVMTypeOf(rhs_value)); + if (lhs_signed && !rhs_signed && !vector_type && llvm_is_const(lhs_value) && type_size(lhs_type) <= 8) { long long val = LLVMConstIntGetSExtValue(lhs_value); diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index c3a626c9c..d65599998 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -458,7 +458,7 @@ INLINE LLVMValueRef llvm_store_decl_raw(GenContext *context, Decl *decl, LLVMVal INLINE LLVMValueRef llvm_store_to_ptr(GenContext *c, LLVMValueRef destination, BEValue *value); INLINE LLVMValueRef llvm_store_to_ptr_raw(GenContext *c, LLVMValueRef pointer, LLVMValueRef value, Type *type); LLVMValueRef llvm_store_to_ptr_aligned(GenContext *c, LLVMValueRef destination, BEValue *value, AlignSize alignment); -LLVMValueRef llvm_store_to_ptr_raw_aligned(GenContext *context, LLVMValueRef pointer, LLVMValueRef value, AlignSize alignment); +LLVMValueRef llvm_store_to_ptr_raw_aligned(GenContext *c, LLVMValueRef pointer, LLVMValueRef value, AlignSize alignment); void llvm_store_to_ptr_zero(GenContext *context, LLVMValueRef pointer, Type *type); TypeSize llvm_store_size(GenContext *c, LLVMTypeRef type); TypeSize llvm_alloc_size(GenContext *c, LLVMTypeRef type); diff --git a/src/compiler/llvm_codegen_storeload.c b/src/compiler/llvm_codegen_storeload.c index 9de895101..357678750 100644 --- a/src/compiler/llvm_codegen_storeload.c +++ b/src/compiler/llvm_codegen_storeload.c @@ -4,10 +4,11 @@ #include "llvm_codegen_internal.h" -LLVMValueRef llvm_store_to_ptr_raw_aligned(GenContext *context, LLVMValueRef pointer, LLVMValueRef value, AlignSize alignment) +LLVMValueRef llvm_store_to_ptr_raw_aligned(GenContext *c, LLVMValueRef pointer, LLVMValueRef value, AlignSize alignment) { ASSERT(alignment > 0); - LLVMValueRef ref = LLVMBuildStore(context->builder, value, pointer); + assert(LLVMTypeOf(value) != c->bool_type); + LLVMValueRef ref = LLVMBuildStore(c->builder, value, pointer); llvm_set_alignment(ref, alignment); return ref; } diff --git a/test/test_suite7/macros/vasplat_function_call.c3 b/test/test_suite7/macros/vasplat_function_call.c3 deleted file mode 100644 index e69de29bb..000000000