| ... | ... | @@ -1970,10 +1970,6 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1970 | 1970 | .is_err_ptr, |
| 1971 | 1971 | .is_non_err_ptr, |
| 1972 | 1972 | |
| 1973 | | .atomic_store_unordered, |
| 1974 | | .atomic_store_monotonic, |
| 1975 | | .atomic_store_release, |
| 1976 | | .atomic_store_seq_cst, |
| 1977 | 1973 | .err_return_trace, |
| 1978 | 1974 | .set_err_return_trace, |
| 1979 | 1975 | .save_err_return_trace_index, |
| ... | ... | @@ -1987,6 +1983,12 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1987 | 1983 | => |tag| return func.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}), |
| 1988 | 1984 | |
| 1989 | 1985 | .atomic_load => func.airAtomicLoad(inst), |
| 1986 | .atomic_store_unordered, |
| 1987 | .atomic_store_monotonic, |
| 1988 | .atomic_store_release, |
| 1989 | .atomic_store_seq_cst, |
| 1990 | // in WebAssembly, all atomic instructions are sequentially ordered. |
| 1991 | => func.airAtomicStore(inst), |
| 1990 | 1992 | .atomic_rmw => func.airAtomicRmw(inst), |
| 1991 | 1993 | .cmpxchg_weak => func.airCmpxchg(inst), |
| 1992 | 1994 | .cmpxchg_strong => func.airCmpxchg(inst), |
| ... | ... | @@ -6634,7 +6636,13 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6634 | 6636 | try func.emitWValue(ptr_operand); |
| 6635 | 6637 | try func.emitWValue(expected_val); |
| 6636 | 6638 | try func.emitWValue(new_val); |
| 6637 | | try func.addAtomicMemArg(.i32_atomic_rmw_cmpxchg, .{ |
| 6639 | try func.addAtomicMemArg(switch (ty.abiSize(func.target)) { |
| 6640 | 1 => .i32_atomic_rmw8_cmpxchg_u, |
| 6641 | 2 => .i32_atomic_rmw16_cmpxchg_u, |
| 6642 | 4 => .i32_atomic_rmw_cmpxchg, |
| 6643 | 8 => .i32_atomic_rmw_cmpxchg, |
| 6644 | else => |size| return func.fail("TODO: implement `@cmpxchg` for types with abi size '{d}'", .{size}), |
| 6645 | }, .{ |
| 6638 | 6646 | .offset = ptr_operand.offset(), |
| 6639 | 6647 | .alignment = ty.abiAlignment(func.target), |
| 6640 | 6648 | }); |
| ... | ... | @@ -6880,3 +6888,32 @@ fn airFence(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6880 | 6888 | |
| 6881 | 6889 | return func.finishAir(inst, .none, &.{}); |
| 6882 | 6890 | } |
| 6891 | |
| 6892 | fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6893 | const bin_op = func.air.instructions.items(.data)[inst].bin_op; |
| 6894 | |
| 6895 | const ptr = try func.resolveInst(bin_op.lhs); |
| 6896 | const operand = try func.resolveInst(bin_op.rhs); |
| 6897 | const ptr_ty = func.air.typeOf(bin_op.lhs); |
| 6898 | const ty = ptr_ty.childType(); |
| 6899 | |
| 6900 | if (func.useAtomicFeature()) { |
| 6901 | const tag: wasm.AtomicsOpcode = switch (ty.abiSize(func.target)) { |
| 6902 | 1 => .i32_atomic_store8, |
| 6903 | 2 => .i32_atomic_store16, |
| 6904 | 4 => .i32_atomic_store, |
| 6905 | 8 => .i64_atomic_store, |
| 6906 | else => |size| return func.fail("TODO: @atomicLoad for types with abi size {d}", .{size}), |
| 6907 | }; |
| 6908 | try func.emitWValue(ptr); |
| 6909 | try func.lowerToStack(operand); |
| 6910 | try func.addAtomicMemArg(tag, .{ |
| 6911 | .offset = ptr.offset(), |
| 6912 | .alignment = ty.abiAlignment(func.target), |
| 6913 | }); |
| 6914 | } else { |
| 6915 | try func.store(ptr, operand, ty, 0); |
| 6916 | } |
| 6917 | |
| 6918 | return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs }); |
| 6919 | } |