| ... | @@ -940,6 +940,14 @@ fn addMemArg(func: *CodeGen, tag: Mir.Inst.Tag, mem_arg: Mir.MemArg) error{OutOf | ... | @@ -940,6 +940,14 @@ fn addMemArg(func: *CodeGen, tag: Mir.Inst.Tag, mem_arg: Mir.MemArg) error{OutOf |
| 940 | try func.addInst(.{ .tag = tag, .data = .{ .payload = extra_index } }); | 940 | try func.addInst(.{ .tag = tag, .data = .{ .payload = extra_index } }); |
| 941 | } | 941 | } |
| 942 | | 942 | |
| | 943 | /// Inserts an instruction from the 'atomics' feature which accesses wasm's linear memory dependent on the |
| | 944 | /// given `tag`. |
| | 945 | fn addAtomicMemArg(func: *CodeGen, tag: wasm.AtomicsOpcode, mem_arg: Mir.MemArg) error{OutOfMemory}!void { |
| | 946 | const extra_index = try func.addExtra(@as(struct { val: u32 }, .{ .val = wasm.atomicsOpcode(tag) })); |
| | 947 | _ = try func.addExtra(mem_arg); |
| | 948 | try func.addInst(.{ .tag = .atomics_prefix, .data = .{ .payload = extra_index } }); |
| | 949 | } |
| | 950 | |
| 943 | /// Appends entries to `mir_extra` based on the type of `extra`. | 951 | /// Appends entries to `mir_extra` based on the type of `extra`. |
| 944 | /// Returns the index into `mir_extra` | 952 | /// Returns the index into `mir_extra` |
| 945 | fn addExtra(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32 { | 953 | fn addExtra(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32 { |
| ... | @@ -6518,6 +6526,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { | ... | @@ -6518,6 +6526,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { |
| 6518 | return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs); | 6526 | return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs); |
| 6519 | } | 6527 | } |
| 6520 | | 6528 | |
| | 6529 | <<<<<<< HEAD |
| 6521 | fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 6530 | fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6522 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | 6531 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 6523 | | 6532 | |
| ... | @@ -6599,6 +6608,10 @@ fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6599,6 +6608,10 @@ fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6599 | return func.finishAir(inst, result, &.{ty_op.operand}); | 6608 | return func.finishAir(inst, result, &.{ty_op.operand}); |
| 6600 | } | 6609 | } |
| 6601 | | 6610 | |
| | 6611 | inline fn useAtomicFeature(func: *const CodeGen) bool { |
| | 6612 | return std.Target.wasm.featureSetHas(func.target.cpu.features, .atomics); |
| | 6613 | } |
| | 6614 | |
| 6602 | fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 6615 | fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6603 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; | 6616 | const ty_pl = func.air.instructions.items(.data)[inst].ty_pl; |
| 6604 | const extra = func.air.extraData(Air.Cmpxchg, ty_pl.payload).data; | 6617 | const extra = func.air.extraData(Air.Cmpxchg, ty_pl.payload).data; |
| ... | @@ -6611,18 +6624,35 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -6611,18 +6624,35 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6611 | const expected_val = try func.resolveInst(extra.expected_value); | 6624 | const expected_val = try func.resolveInst(extra.expected_value); |
| 6612 | const new_val = try func.resolveInst(extra.new_value); | 6625 | const new_val = try func.resolveInst(extra.new_value); |
| 6613 | | 6626 | |
| 6614 | const ptr_val = try WValue.toLocal(try func.load(ptr_operand, ty, 0), func, ty); | 6627 | const ptr_val = if (func.useAtomicFeature()) val: { |
| | 6628 | const val_local = try func.allocLocal(ty); |
| | 6629 | try func.emitWValue(ptr_operand); |
| | 6630 | try func.emitWValue(expected_val); |
| | 6631 | try func.emitWValue(new_val); |
| | 6632 | try func.addAtomicMemArg(.i32_atomic_rmw_cmpxchg, .{ |
| | 6633 | .offset = ptr_operand.offset(), |
| | 6634 | .alignment = ty.abiAlignment(func.target), |
| | 6635 | }); |
| | 6636 | try func.addLabel(.local_tee, val_local.local.value); |
| | 6637 | _ = try func.cmp(.stack, expected_val, ty, .eq); |
| | 6638 | break :val val_local; |
| | 6639 | } else val: { |
| | 6640 | const ptr_val = try WValue.toLocal(try func.load(ptr_operand, ty, 0), func, ty); |
| | 6641 | |
| | 6642 | try func.lowerToStack(ptr_operand); |
| | 6643 | try func.emitWValue(new_val); |
| | 6644 | try func.emitWValue(ptr_val); |
| | 6645 | const cmp_tmp = try func.cmp(ptr_val, expected_val, ty, .eq); |
| | 6646 | const cmp_result = try cmp_tmp.toLocal(func, Type.bool); |
| | 6647 | try func.emitWValue(cmp_result); |
| | 6648 | try func.addTag(.select); |
| | 6649 | try func.store(.stack, .stack, ty, 0); |
| | 6650 | try func.emitWValue(cmp_result); |
| | 6651 | |
| | 6652 | break :val ptr_val; |
| | 6653 | }; |
| 6615 | | 6654 | |
| 6616 | try func.lowerToStack(ptr_operand); | | |
| 6617 | try func.emitWValue(new_val); | | |
| 6618 | try func.emitWValue(ptr_val); | | |
| 6619 | const cmp_tmp = try func.cmp(ptr_val, expected_val, ty, .eq); | | |
| 6620 | const cmp_result = try cmp_tmp.toLocal(func, Type.bool); | | |
| 6621 | try func.emitWValue(cmp_result); | | |
| 6622 | try func.addTag(.select); | | |
| 6623 | try func.store(.stack, .stack, ty, 0); | | |
| 6624 | try func.addImm32(-1); | 6655 | try func.addImm32(-1); |
| 6625 | try func.emitWValue(cmp_result); | | |
| 6626 | try func.addTag(.i32_xor); | 6656 | try func.addTag(.i32_xor); |
| 6627 | try func.addImm32(1); | 6657 | try func.addImm32(1); |
| 6628 | try func.addTag(.i32_and); | 6658 | try func.addTag(.i32_and); |