aboutsummaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2023-04-24 18:42:28 +0200
committerLuuk de Gram <luuk@degram.dev>2023-04-26 16:28:41 +0200
commit0e3303ccd9985f4336ccde779b2f1b90f130d7a2 (patch)
treee7d7b2b23b7ec892a28c9c91cda2e3efc0024f54 /src/arch
parentb19c258f045aa1653b4e38ba2ff96302d914eea2 (diff)
downloadzig-0e3303ccd9985f4336ccde779b2f1b90f130d7a2.tar.gz
zig-0e3303ccd9985f4336ccde779b2f1b90f130d7a2.zip
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.
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/wasm/CodeGen.zig19
-rw-r--r--src/arch/wasm/Emit.zig6
2 files changed, 24 insertions, 1 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index d617ad9789..38b96efb09 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -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, &.{});
+}
diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig
index ec5d9d9880..bfa5324dc6 100644
--- a/src/arch/wasm/Emit.zig
+++ b/src/arch/wasm/Emit.zig
@@ -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)}),
}
}