diff options
| author | Luuk de Gram <luuk@degram.dev> | 2023-04-18 21:06:03 +0200 |
|---|---|---|
| committer | Luuk de Gram <luuk@degram.dev> | 2023-04-26 16:28:37 +0200 |
| commit | 5bbd482286930a17d37ef46396c419edee98573c (patch) | |
| tree | 94635a77cf214f78e025b8a27c3eb788f062e506 /src | |
| parent | 7285eedcd26b92afb03c313a167133103a78ded5 (diff) | |
| download | zig-5bbd482286930a17d37ef46396c419edee98573c.tar.gz zig-5bbd482286930a17d37ef46396c419edee98573c.zip | |
wasm: implement `cmpxchg{weak/strong}`
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/wasm/CodeGen.zig | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 9bf39b73f1..cdeaa09b5e 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1956,8 +1956,6 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { .is_err_ptr, .is_non_err_ptr, - .cmpxchg_weak, - .cmpxchg_strong, .fence, .atomic_load, .atomic_store_unordered, @@ -1977,6 +1975,9 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { .c_va_start, => |tag| return func.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}), + .cmpxchg_weak => func.airCmpxchg(inst), + .cmpxchg_strong => func.airCmpxchg(inst), + .add_optimized, .addwrap_optimized, .sub_optimized, @@ -6597,3 +6598,39 @@ fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { return func.finishAir(inst, result, &.{ty_op.operand}); } + +fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { + const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; + const extra = func.air.extraData(Air.Cmpxchg, ty_pl.payload).data; + + const ptr_ty = func.air.typeOf(extra.ptr); + const ty = ptr_ty.childType(); + const result_ty = func.air.typeOfIndex(inst); + + const ptr_operand = try func.resolveInst(extra.ptr); + const expected_val = try func.resolveInst(extra.expected_value); + const new_val = try func.resolveInst(extra.new_value); + + const ptr_val = try WValue.toLocal(try func.load(ptr_operand, ty, 0), func, ty); + + try func.lowerToStack(ptr_operand); + try func.emitWValue(new_val); + try func.emitWValue(ptr_val); + const cmp_tmp = try func.cmp(ptr_val, expected_val, ty, .eq); + const cmp_result = try cmp_tmp.toLocal(func, Type.bool); + try func.emitWValue(cmp_result); + try func.addTag(.select); + try func.store(.stack, .stack, ty, 0); + try func.addImm32(-1); + try func.emitWValue(cmp_result); + try func.addTag(.i32_xor); + try func.addImm32(1); + try func.addTag(.i32_and); + const and_result = try WValue.toLocal(.stack, func, Type.bool); + + const result_ptr = try func.allocStack(result_ty); + try func.store(result_ptr, and_result, Type.bool, @intCast(u32, ty.abiSize(func.target))); + try func.store(result_ptr, ptr_val, ty, 0); + + return func.finishAir(inst, result_ptr, &.{ extra.ptr, extra.new_value, extra.expected_value }); +} |
