authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-03-10 22:33:32+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-03-10 22:33:32+02:00
log8dc188ebe06b5b78dcead521561858fc27e25204
treed5c05dbe81a0afc0a738dec42f2809a569a3f248
parent675f01f1768aa08c307640b53e8a5240fa190fab
signaturelock-open Commit is signed but in an unrecognized format.

support atomic operations with bools


3 files changed, 59 insertions(+), 0 deletions(-)

src/codegen.cpp+43
...@@ -5224,6 +5224,15 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I...@@ -5224,6 +5224,15 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
5224 LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);5224 LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
5225 LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);5225 LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
52265226
5227 ZigType *operand_type = instruction->new_value->value->type;
5228 if (operand_type->id == ZigTypeIdBool) {
5229 // treat bool as u8
5230 ptr_val = LLVMBuildBitCast(g->builder, ptr_val,
5231 LLVMPointerType(g->builtin_types.entry_u8->llvm_type, 0), "");
5232 cmp_val = LLVMConstZExt(cmp_val, g->builtin_types.entry_u8->llvm_type);
5233 new_val = LLVMConstZExt(new_val, g->builtin_types.entry_u8->llvm_type);
5234 }
5235
5227 LLVMAtomicOrdering success_order = to_LLVMAtomicOrdering(instruction->success_order);5236 LLVMAtomicOrdering success_order = to_LLVMAtomicOrdering(instruction->success_order);
5228 LLVMAtomicOrdering failure_order = to_LLVMAtomicOrdering(instruction->failure_order);5237 LLVMAtomicOrdering failure_order = to_LLVMAtomicOrdering(instruction->failure_order);
52295238
...@@ -5236,6 +5245,9 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I...@@ -5236,6 +5245,9 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
52365245
5237 if (!handle_is_ptr(g, optional_type)) {5246 if (!handle_is_ptr(g, optional_type)) {
5238 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");5247 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
5248 if (operand_type->id == ZigTypeIdBool) {
5249 payload_val = LLVMBuildTrunc(g->builder, payload_val, g->builtin_types.entry_bool->llvm_type, "");
5250 }
5239 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");5251 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
5240 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");5252 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");
5241 }5253 }
...@@ -5250,6 +5262,9 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I...@@ -5250,6 +5262,9 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
5250 ir_assert(type_has_bits(g, child_type), &instruction->base);5262 ir_assert(type_has_bits(g, child_type), &instruction->base);
52515263
5252 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");5264 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
5265 if (operand_type->id == ZigTypeIdBool) {
5266 payload_val = LLVMBuildTrunc(g->builder, payload_val, g->builtin_types.entry_bool->llvm_type, "");
5267 }
5253 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");5268 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
5254 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);5269 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
52555270
...@@ -5827,6 +5842,16 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable...@@ -5827,6 +5842,16 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable
5827 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);5842 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
5828 LLVMValueRef operand = ir_llvm_value(g, instruction->operand);5843 LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
58295844
5845 if (operand_type->id == ZigTypeIdBool) {
5846 // treat bool as u8
5847 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,
5848 LLVMPointerType(g->builtin_types.entry_u8->llvm_type, 0), "");
5849 LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, g->builtin_types.entry_u8->llvm_type, "");
5850 LLVMValueRef uncasted_result = ZigLLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering,
5851 g->is_single_threaded);
5852 return LLVMBuildTrunc(g->builder, uncasted_result, g->builtin_types.entry_bool->llvm_type, "");
5853 }
5854
5830 if (get_codegen_ptr_type_bail(g, operand_type) == nullptr) {5855 if (get_codegen_ptr_type_bail(g, operand_type) == nullptr) {
5831 return ZigLLVMBuildAtomicRMW(g->builder, op, ptr, operand, ordering, g->is_single_threaded);5856 return ZigLLVMBuildAtomicRMW(g->builder, op, ptr, operand, ordering, g->is_single_threaded);
5832 }5857 }
...@@ -5845,6 +5870,16 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutableGen *executabl...@@ -5845,6 +5870,16 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutableGen *executabl
5845{5870{
5846 LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering);5871 LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering);
5847 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);5872 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
5873
5874 ZigType *operand_type = instruction->ptr->value->type->data.pointer.child_type;
5875 if (operand_type->id == ZigTypeIdBool) {
5876 // treat bool as u8
5877 ptr = LLVMBuildBitCast(g->builder, ptr,
5878 LLVMPointerType(g->builtin_types.entry_u8->llvm_type, 0), "");
5879 LLVMValueRef load_inst = gen_load(g, ptr, instruction->ptr->value->type, "");
5880 LLVMSetOrdering(load_inst, ordering);
5881 return LLVMBuildTrunc(g->builder, load_inst, g->builtin_types.entry_bool->llvm_type, "");
5882 }
5848 LLVMValueRef load_inst = gen_load(g, ptr, instruction->ptr->value->type, "");5883 LLVMValueRef load_inst = gen_load(g, ptr, instruction->ptr->value->type, "");
5849 LLVMSetOrdering(load_inst, ordering);5884 LLVMSetOrdering(load_inst, ordering);
5850 return load_inst;5885 return load_inst;
...@@ -5856,6 +5891,14 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executab...@@ -5856,6 +5891,14 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executab
5856 LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering);5891 LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering);
5857 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);5892 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
5858 LLVMValueRef value = ir_llvm_value(g, instruction->value);5893 LLVMValueRef value = ir_llvm_value(g, instruction->value);
5894
5895 ZigType *operand_type = instruction->value->value->type;
5896 if (operand_type->id == ZigTypeIdBool) {
5897 // treat bool as u8
5898 ptr = LLVMBuildBitCast(g->builder, ptr,
5899 LLVMPointerType(g->builtin_types.entry_u8->llvm_type, 0), "");
5900 value = LLVMConstZExt(value, g->builtin_types.entry_u8->llvm_type);
5901 }
5859 LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value->type);5902 LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value->type);
5860 LLVMSetOrdering(store_inst, ordering);5903 LLVMSetOrdering(store_inst, ordering);
5861 return nullptr;5904 return nullptr;
src/ir.cpp+6
...@@ -28357,6 +28357,8 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op) {...@@ -28357,6 +28357,8 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op) {
28357 max_atomic_bits, (uint32_t) operand_type->data.floating.bit_count));28357 max_atomic_bits, (uint32_t) operand_type->data.floating.bit_count));
28358 return ira->codegen->builtin_types.entry_invalid;28358 return ira->codegen->builtin_types.entry_invalid;
28359 }28359 }
28360 } else if (operand_type->id == ZigTypeIdBool) {
28361 // will be treated as u8
28360 } else {28362 } else {
28361 Error err;28363 Error err;
28362 ZigType *operand_ptr_type;28364 ZigType *operand_ptr_type;
...@@ -28397,6 +28399,10 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto...@@ -28397,6 +28399,10 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
28397 ir_add_error(ira, &instruction->op->base,28399 ir_add_error(ira, &instruction->op->base,
28398 buf_sprintf("@atomicRmw on enum only works with .Xchg"));28400 buf_sprintf("@atomicRmw on enum only works with .Xchg"));
28399 return ira->codegen->invalid_inst_gen;28401 return ira->codegen->invalid_inst_gen;
28402 } else if (operand_type->id == ZigTypeIdBool && op != AtomicRmwOp_xchg) {
28403 ir_add_error(ira, &instruction->op->base,
28404 buf_sprintf("@atomicRmw on bool only works with .Xchg"));
28405 return ira->codegen->invalid_inst_gen;
28400 } else if (operand_type->id == ZigTypeIdFloat && op > AtomicRmwOp_sub) {28406 } else if (operand_type->id == ZigTypeIdFloat && op > AtomicRmwOp_sub) {
28401 ir_add_error(ira, &instruction->op->base,28407 ir_add_error(ira, &instruction->op->base,
28402 buf_sprintf("@atomicRmw with float only works with .Xchg, .Add and .Sub"));28408 buf_sprintf("@atomicRmw with float only works with .Xchg, .Add and .Sub"));
test/stage1/behavior/atomics.zig+10
...@@ -161,3 +161,13 @@ fn testAtomicRmwFloat() void {...@@ -161,3 +161,13 @@ fn testAtomicRmwFloat() void {
161 _ = @atomicRmw(f32, &x, .Sub, 2, .SeqCst);161 _ = @atomicRmw(f32, &x, .Sub, 2, .SeqCst);
162 expect(x == 4);162 expect(x == 4);
163}163}
164
165test "atomics with bool" {
166 var x = false;
167 @atomicStore(bool, &x, true, .SeqCst);
168 expect(x == true);
169 expect(@atomicLoad(bool, &x, .SeqCst) == true);
170 expect(@atomicRmw(bool, &x, .Xchg, false, .SeqCst) == true);
171 expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst) == null);
172 expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst).? == true);
173}