| ... | ... | @@ -6631,11 +6631,13 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6631 | 6631 | const expected_val = try func.resolveInst(extra.expected_value); |
| 6632 | 6632 | const new_val = try func.resolveInst(extra.new_value); |
| 6633 | 6633 | |
| 6634 | const cmp_result = try func.allocLocal(Type.bool); |
| 6635 | |
| 6634 | 6636 | const ptr_val = if (func.useAtomicFeature()) val: { |
| 6635 | 6637 | const val_local = try func.allocLocal(ty); |
| 6636 | 6638 | try func.emitWValue(ptr_operand); |
| 6637 | | try func.emitWValue(expected_val); |
| 6638 | | try func.emitWValue(new_val); |
| 6639 | try func.lowerToStack(expected_val); |
| 6640 | try func.lowerToStack(new_val); |
| 6639 | 6641 | try func.addAtomicMemArg(switch (ty.abiSize(func.target)) { |
| 6640 | 6642 | 1 => .i32_atomic_rmw8_cmpxchg_u, |
| 6641 | 6643 | 2 => .i32_atomic_rmw16_cmpxchg_u, |
| ... | ... | @@ -6648,32 +6650,43 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6648 | 6650 | }); |
| 6649 | 6651 | try func.addLabel(.local_tee, val_local.local.value); |
| 6650 | 6652 | _ = try func.cmp(.stack, expected_val, ty, .eq); |
| 6653 | try func.addLabel(.local_set, cmp_result.local.value); |
| 6651 | 6654 | break :val val_local; |
| 6652 | 6655 | } else val: { |
| 6656 | if (ty.abiSize(func.target) > 8) { |
| 6657 | return func.fail("TODO: Implement `@cmpxchg` for types larger than abi size of 8 bytes", .{}); |
| 6658 | } |
| 6653 | 6659 | const ptr_val = try WValue.toLocal(try func.load(ptr_operand, ty, 0), func, ty); |
| 6654 | 6660 | |
| 6655 | 6661 | try func.lowerToStack(ptr_operand); |
| 6656 | | try func.emitWValue(new_val); |
| 6662 | try func.lowerToStack(new_val); |
| 6657 | 6663 | try func.emitWValue(ptr_val); |
| 6658 | | const cmp_tmp = try func.cmp(ptr_val, expected_val, ty, .eq); |
| 6659 | | const cmp_result = try cmp_tmp.toLocal(func, Type.bool); |
| 6660 | | try func.emitWValue(cmp_result); |
| 6664 | _ = try func.cmp(ptr_val, expected_val, ty, .eq); |
| 6665 | try func.addLabel(.local_tee, cmp_result.local.value); |
| 6661 | 6666 | try func.addTag(.select); |
| 6662 | 6667 | try func.store(.stack, .stack, ty, 0); |
| 6663 | | try func.emitWValue(cmp_result); |
| 6664 | 6668 | |
| 6665 | 6669 | break :val ptr_val; |
| 6666 | 6670 | }; |
| 6667 | 6671 | |
| 6668 | | try func.addImm32(-1); |
| 6669 | | try func.addTag(.i32_xor); |
| 6670 | | try func.addImm32(1); |
| 6671 | | try func.addTag(.i32_and); |
| 6672 | | const and_result = try WValue.toLocal(.stack, func, Type.bool); |
| 6673 | | |
| 6674 | | const result_ptr = try func.allocStack(result_ty); |
| 6675 | | try func.store(result_ptr, and_result, Type.bool, @intCast(u32, ty.abiSize(func.target))); |
| 6676 | | try func.store(result_ptr, ptr_val, ty, 0); |
| 6672 | const result_ptr = if (isByRef(result_ty, func.target)) val: { |
| 6673 | try func.emitWValue(cmp_result); |
| 6674 | try func.addImm32(-1); |
| 6675 | try func.addTag(.i32_xor); |
| 6676 | try func.addImm32(1); |
| 6677 | try func.addTag(.i32_and); |
| 6678 | const and_result = try WValue.toLocal(.stack, func, Type.bool); |
| 6679 | const result_ptr = try func.allocStack(result_ty); |
| 6680 | try func.store(result_ptr, and_result, Type.bool, @intCast(u32, ty.abiSize(func.target))); |
| 6681 | try func.store(result_ptr, ptr_val, ty, 0); |
| 6682 | break :val result_ptr; |
| 6683 | } else val: { |
| 6684 | try func.addImm32(0); |
| 6685 | try func.emitWValue(ptr_val); |
| 6686 | try func.emitWValue(cmp_result); |
| 6687 | try func.addTag(.select); |
| 6688 | break :val try WValue.toLocal(.stack, func, result_ty); |
| 6689 | }; |
| 6677 | 6690 | |
| 6678 | 6691 | return func.finishAir(inst, result_ptr, &.{ extra.ptr, extra.new_value, extra.expected_value }); |
| 6679 | 6692 | } |