authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-04-25 19:52:36+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-04-26 16:28:41+02:00
logb26a46d05b9a22b35f385948bc24059600213751
tree18fc7ad908cdd327403a85d6388e521b028e77b9
parent7c09e09457fdd04fa3c28d32ecc91ea4454c09aa
signaturelock-open Commit is signed but in an unrecognized format.

wasm: support pointers in `cmpxchg`


1 files changed, 29 insertions(+), 16 deletions(-)

src/arch/wasm/CodeGen.zig+29-16
......@@ -6631,11 +6631,13 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
66316631 const expected_val = try func.resolveInst(extra.expected_value);
66326632 const new_val = try func.resolveInst(extra.new_value);
66336633
6634 const cmp_result = try func.allocLocal(Type.bool);
6635
66346636 const ptr_val = if (func.useAtomicFeature()) val: {
66356637 const val_local = try func.allocLocal(ty);
66366638 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);
66396641 try func.addAtomicMemArg(switch (ty.abiSize(func.target)) {
66406642 1 => .i32_atomic_rmw8_cmpxchg_u,
66416643 2 => .i32_atomic_rmw16_cmpxchg_u,
......@@ -6648,32 +6650,43 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
66486650 });
66496651 try func.addLabel(.local_tee, val_local.local.value);
66506652 _ = try func.cmp(.stack, expected_val, ty, .eq);
6653 try func.addLabel(.local_set, cmp_result.local.value);
66516654 break :val val_local;
66526655 } 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 }
66536659 const ptr_val = try WValue.toLocal(try func.load(ptr_operand, ty, 0), func, ty);
66546660
66556661 try func.lowerToStack(ptr_operand);
6656 try func.emitWValue(new_val);
6662 try func.lowerToStack(new_val);
66576663 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);
66616666 try func.addTag(.select);
66626667 try func.store(.stack, .stack, ty, 0);
6663 try func.emitWValue(cmp_result);
66646668
66656669 break :val ptr_val;
66666670 };
66676671
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 };
66776690
66786691 return func.finishAir(inst, result_ptr, &.{ extra.ptr, extra.new_value, extra.expected_value });
66796692}