aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2023-04-21 16:27:24 +0200
committerLuuk de Gram <luuk@degram.dev>2023-04-26 16:28:40 +0200
commitfd47eddc862b0a5bd90949fe21cf87a716c5464c (patch)
treeff0553de1166f9d69cb82085be54864dfc36d907 /src
parent650976b2262a9ce715ebeb1e5949b7b453b75f2f (diff)
downloadzig-fd47eddc862b0a5bd90949fe21cf87a716c5464c.tar.gz
zig-fd47eddc862b0a5bd90949fe21cf87a716c5464c.zip
wasm: implement `@atomicLoad`
Uses the atomic instructions when cpu feature is enabled, otherwise lowers it down to a regular load.
Diffstat (limited to 'src')
-rw-r--r--src/arch/wasm/CodeGen.zig28
-rw-r--r--src/arch/wasm/Emit.zig7
2 files changed, 34 insertions, 1 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index 786b3fea76..fb27f8f343 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -1965,7 +1965,6 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
.is_non_err_ptr,
.fence,
- .atomic_load,
.atomic_store_unordered,
.atomic_store_monotonic,
.atomic_store_release,
@@ -1983,6 +1982,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
.c_va_start,
=> |tag| return func.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
+ .atomic_load => func.airAtomicLoad(inst),
.cmpxchg_weak => func.airCmpxchg(inst),
.cmpxchg_strong => func.airCmpxchg(inst),
@@ -6664,3 +6664,29 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
return func.finishAir(inst, result_ptr, &.{ extra.ptr, extra.new_value, extra.expected_value });
}
+
+fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
+ const atomic_load = func.air.instructions.items(.data)[inst].atomic_load;
+ const ptr = try func.resolveInst(atomic_load.ptr);
+ const ty = func.air.typeOfIndex(inst);
+
+ if (func.useAtomicFeature()) {
+ const tag: wasm.AtomicsOpcode = switch (ty.abiSize(func.target)) {
+ 1 => .i32_atomic_load8_u,
+ 2 => .i32_atomic_load16_u,
+ 4 => .i32_atomic_load,
+ 8 => .i64_atomic_load,
+ else => |size| return func.fail("TODO: @atomicLoad for integers with abi size {d}", .{size}),
+ };
+ try func.emitWValue(ptr);
+ try func.addAtomicMemArg(tag, .{
+ .offset = ptr.offset(),
+ .alignment = ty.abiAlignment(func.target),
+ });
+ } else {
+ _ = try func.load(ptr, ty, 0);
+ }
+
+ const result = try WValue.toLocal(.stack, func, ty);
+ return func.finishAir(inst, result, &.{atomic_load.ptr});
+}
diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig
index 173a2ac672..420f0d7606 100644
--- a/src/arch/wasm/Emit.zig
+++ b/src/arch/wasm/Emit.zig
@@ -529,6 +529,13 @@ fn emitAtomic(emit: *Emit, inst: Mir.Inst.Index) !void {
switch (@intToEnum(std.wasm.AtomicsOpcode, opcode)) {
.i32_atomic_rmw_cmpxchg,
.i64_atomic_rmw_cmpxchg,
+ .i32_atomic_load,
+ .i64_atomic_load,
+ .i32_atomic_load8_u,
+ .i32_atomic_load16_u,
+ .i64_atomic_load8_u,
+ .i64_atomic_load16_u,
+ .i64_atomic_load32_u,
=> {
const mem_arg = emit.mir.extraData(Mir.MemArg, extra_index + 1).data;
try encodeMemArg(mem_arg, writer);