mirror of
https://github.com/ziglang/zig.git
synced 2026-02-03 13:13:40 +00:00
wasm: implement @fence
Uses the `atomic.fence` instruction for multi-thread-enabled builds where the `atomics` feature is enabled for the wasm32 target. In all other cases, this lowers to a nop.
This commit is contained in:
parent
b19c258f04
commit
0e3303ccd9
@ -948,6 +948,12 @@ fn addAtomicMemArg(func: *CodeGen, tag: wasm.AtomicsOpcode, mem_arg: Mir.MemArg)
|
||||
try func.addInst(.{ .tag = .atomics_prefix, .data = .{ .payload = extra_index } });
|
||||
}
|
||||
|
||||
/// Helper function to emit atomic mir opcodes.
|
||||
fn addAtomicTag(func: *CodeGen, tag: wasm.AtomicsOpcode) error{OutOfMemory}!void {
|
||||
const extra_index = try func.addExtra(@as(struct { val: u32 }, .{ .val = wasm.atomicsOpcode(tag) }));
|
||||
try func.addInst(.{ .tag = .atomics_prefix, .data = .{ .payload = extra_index } });
|
||||
}
|
||||
|
||||
/// Appends entries to `mir_extra` based on the type of `extra`.
|
||||
/// Returns the index into `mir_extra`
|
||||
fn addExtra(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32 {
|
||||
@ -1964,7 +1970,6 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
.is_err_ptr,
|
||||
.is_non_err_ptr,
|
||||
|
||||
.fence,
|
||||
.atomic_store_unordered,
|
||||
.atomic_store_monotonic,
|
||||
.atomic_store_release,
|
||||
@ -1985,6 +1990,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
.atomic_rmw => func.airAtomicRmw(inst),
|
||||
.cmpxchg_weak => func.airCmpxchg(inst),
|
||||
.cmpxchg_strong => func.airCmpxchg(inst),
|
||||
.fence => func.airFence(inst),
|
||||
|
||||
.add_optimized,
|
||||
.addwrap_optimized,
|
||||
@ -6863,3 +6869,14 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
return func.finishAir(inst, result, &.{ pl_op.operand, extra.operand });
|
||||
}
|
||||
}
|
||||
|
||||
fn airFence(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
// Only when the atomic feature is enabled, and we're not building
|
||||
// for a single-threaded build, can we emit the `fence` instruction.
|
||||
// In all other cases, we emit no instructions for a fence.
|
||||
if (func.useAtomicFeature() and !func.bin_file.base.options.single_threaded) {
|
||||
try func.addAtomicTag(.atomic_fence);
|
||||
}
|
||||
|
||||
return func.finishAir(inst, .none, &.{});
|
||||
}
|
||||
|
||||
@ -595,6 +595,12 @@ fn emitAtomic(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
const mem_arg = emit.mir.extraData(Mir.MemArg, extra_index + 1).data;
|
||||
try encodeMemArg(mem_arg, writer);
|
||||
},
|
||||
.atomic_fence => {
|
||||
// TODO: When multi-memory proposal is accepted and implemented in the compiler,
|
||||
// change this to (user-)specified index, rather than hardcode it to memory index 0.
|
||||
const memory_index: u32 = 0;
|
||||
try leb128.writeULEB128(writer, memory_index);
|
||||
},
|
||||
else => |tag| return emit.fail("TODO: Implement atomic instruction: {s}", .{@tagName(tag)}),
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user