authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-12-18 15:02:00-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:35-08:00
log2d899e9a9f0864385939955902e0ba5f322176fc
treee2bb5f12a7056e36576be6e07694f7c945889a10
parent06303448942c387aa4b9d564bcc918ad27e3940a

wasm codegen: fix wrong union field for locals


1 files changed, 47 insertions(+), 51 deletions(-)

src/arch/wasm/CodeGen.zig+47-51
...@@ -190,7 +190,7 @@ const WValue = union(enum) {...@@ -190,7 +190,7 @@ const WValue = union(enum) {
190 switch (value) {190 switch (value) {
191 .stack => {191 .stack => {
192 const new_local = try gen.allocLocal(ty);192 const new_local = try gen.allocLocal(ty);
193 try gen.addLabel(.local_set, new_local.local.value);193 try gen.addLocal(.local_set, new_local.local.value);
194 return new_local;194 return new_local;
195 },195 },
196 .local, .stack_offset => return value,196 .local, .stack_offset => return value,
...@@ -237,9 +237,6 @@ const Op = enum {...@@ -237,9 +237,6 @@ const Op = enum {
237 call_indirect,237 call_indirect,
238 drop,238 drop,
239 select,239 select,
240 local_get,
241 local_set,
242 local_tee,
243 global_get,240 global_get,
244 global_set,241 global_set,
245 load,242 load,
...@@ -318,9 +315,6 @@ fn buildOpcode(args: OpcodeBuildArguments) std.wasm.Opcode {...@@ -318,9 +315,6 @@ fn buildOpcode(args: OpcodeBuildArguments) std.wasm.Opcode {
318 .call_indirect => unreachable,315 .call_indirect => unreachable,
319 .drop => unreachable,316 .drop => unreachable,
320 .select => unreachable,317 .select => unreachable,
321 .local_get => unreachable,
322 .local_set => unreachable,
323 .local_tee => unreachable,
324 .global_get => unreachable,318 .global_get => unreachable,
325 .global_set => unreachable,319 .global_set => unreachable,
326320
...@@ -681,13 +675,11 @@ test "Wasm - buildOpcode" {...@@ -681,13 +675,11 @@ test "Wasm - buildOpcode" {
681 // Make sure buildOpcode is referenced, and test some examples675 // Make sure buildOpcode is referenced, and test some examples
682 const i32_const = buildOpcode(.{ .op = .@"const", .valtype1 = .i32 });676 const i32_const = buildOpcode(.{ .op = .@"const", .valtype1 = .i32 });
683 const end = buildOpcode(.{ .op = .end });677 const end = buildOpcode(.{ .op = .end });
684 const local_get = buildOpcode(.{ .op = .local_get });
685 const i64_extend32_s = buildOpcode(.{ .op = .extend, .valtype1 = .i64, .width = 32, .signedness = .signed });678 const i64_extend32_s = buildOpcode(.{ .op = .extend, .valtype1 = .i64, .width = 32, .signedness = .signed });
686 const f64_reinterpret_i64 = buildOpcode(.{ .op = .reinterpret, .valtype1 = .f64, .valtype2 = .i64 });679 const f64_reinterpret_i64 = buildOpcode(.{ .op = .reinterpret, .valtype1 = .f64, .valtype2 = .i64 });
687680
688 try testing.expectEqual(@as(std.wasm.Opcode, .i32_const), i32_const);681 try testing.expectEqual(@as(std.wasm.Opcode, .i32_const), i32_const);
689 try testing.expectEqual(@as(std.wasm.Opcode, .end), end);682 try testing.expectEqual(@as(std.wasm.Opcode, .end), end);
690 try testing.expectEqual(@as(std.wasm.Opcode, .local_get), local_get);
691 try testing.expectEqual(@as(std.wasm.Opcode, .i64_extend32_s), i64_extend32_s);683 try testing.expectEqual(@as(std.wasm.Opcode, .i64_extend32_s), i64_extend32_s);
692 try testing.expectEqual(@as(std.wasm.Opcode, .f64_reinterpret_i64), f64_reinterpret_i64);684 try testing.expectEqual(@as(std.wasm.Opcode, .f64_reinterpret_i64), f64_reinterpret_i64);
693}685}
...@@ -876,6 +868,10 @@ fn addLabel(cg: *CodeGen, tag: Mir.Inst.Tag, label: u32) error{OutOfMemory}!void...@@ -876,6 +868,10 @@ fn addLabel(cg: *CodeGen, tag: Mir.Inst.Tag, label: u32) error{OutOfMemory}!void
876 try cg.addInst(.{ .tag = tag, .data = .{ .label = label } });868 try cg.addInst(.{ .tag = tag, .data = .{ .label = label } });
877}869}
878870
871fn addLocal(cg: *CodeGen, tag: Mir.Inst.Tag, local: u32) error{OutOfMemory}!void {
872 try cg.addInst(.{ .tag = tag, .data = .{ .local = local } });
873}
874
879/// Accepts an unsigned 32bit integer rather than a signed integer to875/// Accepts an unsigned 32bit integer rather than a signed integer to
880/// prevent us from having to bitcast multiple times as most values876/// prevent us from having to bitcast multiple times as most values
881/// within codegen are represented as unsigned rather than signed.877/// within codegen are represented as unsigned rather than signed.
...@@ -1015,7 +1011,7 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {...@@ -1015,7 +1011,7 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
1015 switch (value) {1011 switch (value) {
1016 .dead => unreachable, // reference to free'd `WValue` (missing reuseOperand?)1012 .dead => unreachable, // reference to free'd `WValue` (missing reuseOperand?)
1017 .none, .stack => {}, // no-op1013 .none, .stack => {}, // no-op
1018 .local => |idx| try cg.addLabel(.local_get, idx.value),1014 .local => |idx| try cg.addLocal(.local_get, idx.value),
1019 .imm32 => |val| try cg.addImm32(val),1015 .imm32 => |val| try cg.addImm32(val),
1020 .imm64 => |val| try cg.addImm64(val),1016 .imm64 => |val| try cg.addImm64(val),
1021 .imm128 => |val| try cg.addImm128(val),1017 .imm128 => |val| try cg.addImm128(val),
...@@ -1063,7 +1059,7 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {...@@ -1063,7 +1059,7 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
1063 });1059 });
1064 }1060 }
1065 },1061 },
1066 .stack_offset => try cg.addLabel(.local_get, cg.bottom_stack_value.local.value), // caller must ensure to address the offset1062 .stack_offset => try cg.addLocal(.local_get, cg.bottom_stack_value.local.value), // caller must ensure to address the offset
1067 }1063 }
1068}1064}
10691065
...@@ -1624,7 +1620,7 @@ fn memcpy(cg: *CodeGen, dst: WValue, src: WValue, len: WValue) !void {...@@ -1624,7 +1620,7 @@ fn memcpy(cg: *CodeGen, dst: WValue, src: WValue, len: WValue) !void {
1624 .wasm32 => try cg.addImm32(0),1620 .wasm32 => try cg.addImm32(0),
1625 .wasm64 => try cg.addImm64(0),1621 .wasm64 => try cg.addImm64(0),
1626 }1622 }
1627 try cg.addLabel(.local_set, offset.local.value);1623 try cg.addLocal(.local_set, offset.local.value);
16281624
1629 // outer block to jump to when loop is done1625 // outer block to jump to when loop is done
1630 try cg.startBlock(.block, std.wasm.block_empty);1626 try cg.startBlock(.block, std.wasm.block_empty);
...@@ -1682,7 +1678,7 @@ fn memcpy(cg: *CodeGen, dst: WValue, src: WValue, len: WValue) !void {...@@ -1682,7 +1678,7 @@ fn memcpy(cg: *CodeGen, dst: WValue, src: WValue, len: WValue) !void {
1682 try cg.addTag(.i64_add);1678 try cg.addTag(.i64_add);
1683 },1679 },
1684 }1680 }
1685 try cg.addLabel(.local_set, offset.local.value);1681 try cg.addLocal(.local_set, offset.local.value);
1686 try cg.addLabel(.br, 0); // jump to start of loop1682 try cg.addLabel(.br, 0); // jump to start of loop
1687 }1683 }
1688 try cg.endBlock(); // close off loop block1684 try cg.endBlock(); // close off loop block
...@@ -1801,7 +1797,7 @@ fn buildPointerOffset(cg: *CodeGen, ptr_value: WValue, offset: u64, action: enum...@@ -1801,7 +1797,7 @@ fn buildPointerOffset(cg: *CodeGen, ptr_value: WValue, offset: u64, action: enum
1801 },1797 },
1802 }1798 }
1803 }1799 }
1804 try cg.addLabel(.local_set, result_ptr.local.value);1800 try cg.addLocal(.local_set, result_ptr.local.value);
1805 return result_ptr;1801 return result_ptr;
1806}1802}
18071803
...@@ -2228,14 +2224,14 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie...@@ -2228,14 +2224,14 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie
2228 // TODO: Make this less fragile and optimize2224 // TODO: Make this less fragile and optimize
2229 } else if (zcu.typeToFunc(fn_ty).?.cc == .wasm_watc and ret_ty.zigTypeTag(zcu) == .@"struct" or ret_ty.zigTypeTag(zcu) == .@"union") {2225 } else if (zcu.typeToFunc(fn_ty).?.cc == .wasm_watc and ret_ty.zigTypeTag(zcu) == .@"struct" or ret_ty.zigTypeTag(zcu) == .@"union") {
2230 const result_local = try cg.allocLocal(ret_ty);2226 const result_local = try cg.allocLocal(ret_ty);
2231 try cg.addLabel(.local_set, result_local.local.value);2227 try cg.addLocal(.local_set, result_local.local.value);
2232 const scalar_type = abi.scalarType(ret_ty, zcu);2228 const scalar_type = abi.scalarType(ret_ty, zcu);
2233 const result = try cg.allocStack(scalar_type);2229 const result = try cg.allocStack(scalar_type);
2234 try cg.store(result, result_local, scalar_type, 0);2230 try cg.store(result, result_local, scalar_type, 0);
2235 break :result_value result;2231 break :result_value result;
2236 } else {2232 } else {
2237 const result_local = try cg.allocLocal(ret_ty);2233 const result_local = try cg.allocLocal(ret_ty);
2238 try cg.addLabel(.local_set, result_local.local.value);2234 try cg.addLocal(.local_set, result_local.local.value);
2239 break :result_value result_local;2235 break :result_value result_local;
2240 }2236 }
2241 };2237 };
...@@ -2817,7 +2813,7 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2817,7 +2813,7 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
28172813
2818 var tmp = try cg.allocLocal(ty);2814 var tmp = try cg.allocLocal(ty);
2819 defer tmp.free(cg);2815 defer tmp.free(cg);
2820 try cg.addLabel(.local_tee, tmp.local.value);2816 try cg.addLocal(.local_tee, tmp.local.value);
28212817
2822 try cg.emitWValue(operand);2818 try cg.emitWValue(operand);
2823 try cg.addTag(.i32_xor);2819 try cg.addTag(.i32_xor);
...@@ -2833,7 +2829,7 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2833,7 +2829,7 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
28332829
2834 var tmp = try cg.allocLocal(ty);2830 var tmp = try cg.allocLocal(ty);
2835 defer tmp.free(cg);2831 defer tmp.free(cg);
2836 try cg.addLabel(.local_tee, tmp.local.value);2832 try cg.addLocal(.local_tee, tmp.local.value);
28372833
2838 try cg.emitWValue(operand);2834 try cg.emitWValue(operand);
2839 try cg.addTag(.i64_xor);2835 try cg.addTag(.i64_xor);
...@@ -2852,7 +2848,7 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2852,7 +2848,7 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
28522848
2853 var tmp = try cg.allocLocal(Type.u64);2849 var tmp = try cg.allocLocal(Type.u64);
2854 defer tmp.free(cg);2850 defer tmp.free(cg);
2855 try cg.addLabel(.local_tee, tmp.local.value);2851 try cg.addLocal(.local_tee, tmp.local.value);
2856 try cg.store(.stack, .stack, Type.u64, mask.offset() + 0);2852 try cg.store(.stack, .stack, Type.u64, mask.offset() + 0);
2857 try cg.emitWValue(tmp);2853 try cg.emitWValue(tmp);
2858 try cg.store(.stack, .stack, Type.u64, mask.offset() + 8);2854 try cg.store(.stack, .stack, Type.u64, mask.offset() + 8);
...@@ -3590,7 +3586,7 @@ fn airBr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3590,7 +3586,7 @@ fn airBr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3590 try cg.lowerToStack(operand);3586 try cg.lowerToStack(operand);
35913587
3592 if (block.value != .none) {3588 if (block.value != .none) {
3593 try cg.addLabel(.local_set, block.value.local.value);3589 try cg.addLocal(.local_set, block.value.local.value);
3594 }3590 }
3595 }3591 }
35963592
...@@ -3625,7 +3621,7 @@ fn airNot(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3625,7 +3621,7 @@ fn airNot(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3625 try cg.emitWValue(operand);3621 try cg.emitWValue(operand);
3626 try cg.addTag(.i32_eqz);3622 try cg.addTag(.i32_eqz);
3627 const not_tmp = try cg.allocLocal(operand_ty);3623 const not_tmp = try cg.allocLocal(operand_ty);
3628 try cg.addLabel(.local_set, not_tmp.local.value);3624 try cg.addLocal(.local_set, not_tmp.local.value);
3629 break :result not_tmp;3625 break :result not_tmp;
3630 } else {3626 } else {
3631 const int_info = operand_ty.intInfo(zcu);3627 const int_info = operand_ty.intInfo(zcu);
...@@ -4788,7 +4784,7 @@ fn memset(cg: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue)...@@ -4788,7 +4784,7 @@ fn memset(cg: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue)
4788 try cg.addTag(.i64_mul);4784 try cg.addTag(.i64_mul);
4789 },4785 },
4790 }4786 }
4791 try cg.addLabel(.local_set, new_len.local.value);4787 try cg.addLocal(.local_set, new_len.local.value);
4792 break :blk new_len;4788 break :blk new_len;
4793 } else len,4789 } else len,
4794 };4790 };
...@@ -4805,7 +4801,7 @@ fn memset(cg: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue)...@@ -4805,7 +4801,7 @@ fn memset(cg: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue)
4805 .wasm32 => try cg.addTag(.i32_add),4801 .wasm32 => try cg.addTag(.i32_add),
4806 .wasm64 => try cg.addTag(.i64_add),4802 .wasm64 => try cg.addTag(.i64_add),
4807 }4803 }
4808 try cg.addLabel(.local_set, end_ptr.local.value);4804 try cg.addLocal(.local_set, end_ptr.local.value);
48094805
4810 // outer block to jump to when loop is done4806 // outer block to jump to when loop is done
4811 try cg.startBlock(.block, std.wasm.block_empty);4807 try cg.startBlock(.block, std.wasm.block_empty);
...@@ -4835,7 +4831,7 @@ fn memset(cg: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue)...@@ -4835,7 +4831,7 @@ fn memset(cg: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue)
4835 try cg.addTag(.i64_add);4831 try cg.addTag(.i64_add);
4836 },4832 },
4837 }4833 }
4838 try cg.addLabel(.local_set, new_ptr.local.value);4834 try cg.addLocal(.local_set, new_ptr.local.value);
48394835
4840 // end of loop4836 // end of loop
4841 try cg.addLabel(.br, 0); // jump to start of loop4837 try cg.addLabel(.br, 0); // jump to start of loop
...@@ -5216,7 +5212,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5216,7 +5212,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5216 try cg.addImm32(0)5212 try cg.addImm32(0)
5217 else5213 else
5218 try cg.addImm64(0);5214 try cg.addImm64(0);
5219 try cg.addLabel(.local_set, result.local.value);5215 try cg.addLocal(.local_set, result.local.value);
52205216
5221 var current_bit: u16 = 0;5217 var current_bit: u16 = 0;
5222 for (elements, 0..) |elem, elem_index| {5218 for (elements, 0..) |elem, elem_index| {
...@@ -5243,7 +5239,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5243,7 +5239,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5243 } else extended_val;5239 } else extended_val;
5244 // we ignore the result as we keep it on the stack to assign it directly to `result`5240 // we ignore the result as we keep it on the stack to assign it directly to `result`
5245 _ = try cg.binOp(.stack, shifted, backing_type, .@"or");5241 _ = try cg.binOp(.stack, shifted, backing_type, .@"or");
5246 try cg.addLabel(.local_set, result.local.value);5242 try cg.addLocal(.local_set, result.local.value);
5247 current_bit += value_bit_size;5243 current_bit += value_bit_size;
5248 }5244 }
5249 break :result_value result;5245 break :result_value result;
...@@ -5399,7 +5395,7 @@ fn cmpOptionals(cg: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: st...@@ -5399,7 +5395,7 @@ fn cmpOptionals(cg: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: st
5399 try cg.addLabel(.br_if, 0);5395 try cg.addLabel(.br_if, 0);
54005396
5401 try cg.addImm32(1);5397 try cg.addImm32(1);
5402 try cg.addLabel(.local_set, result.local.value);5398 try cg.addLocal(.local_set, result.local.value);
5403 try cg.endBlock();5399 try cg.endBlock();
54045400
5405 try cg.emitWValue(result);5401 try cg.emitWValue(result);
...@@ -5642,10 +5638,10 @@ fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5642,10 +5638,10 @@ fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
56425638
5643 const result = if (field_offset != 0) result: {5639 const result = if (field_offset != 0) result: {
5644 const base = try cg.buildPointerOffset(field_ptr, 0, .new);5640 const base = try cg.buildPointerOffset(field_ptr, 0, .new);
5645 try cg.addLabel(.local_get, base.local.value);5641 try cg.addLocal(.local_get, base.local.value);
5646 try cg.addImm32(@intCast(field_offset));5642 try cg.addImm32(@intCast(field_offset));
5647 try cg.addTag(.i32_sub);5643 try cg.addTag(.i32_sub);
5648 try cg.addLabel(.local_set, base.local.value);5644 try cg.addLocal(.local_set, base.local.value);
5649 break :result base;5645 break :result base;
5650 } else cg.reuseOperand(extra.field_ptr, field_ptr);5646 } else cg.reuseOperand(extra.field_ptr, field_ptr);
56515647
...@@ -5676,7 +5672,7 @@ fn airMemcpy(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5676,7 +5672,7 @@ fn airMemcpy(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5676 try cg.emitWValue(slice_len);5672 try cg.emitWValue(slice_len);
5677 try cg.emitWValue(.{ .imm32 = @as(u32, @intCast(ptr_elem_ty.abiSize(zcu))) });5673 try cg.emitWValue(.{ .imm32 = @as(u32, @intCast(ptr_elem_ty.abiSize(zcu))) });
5678 try cg.addTag(.i32_mul);5674 try cg.addTag(.i32_mul);
5679 try cg.addLabel(.local_set, slice_len.local.value);5675 try cg.addLocal(.local_set, slice_len.local.value);
5680 }5676 }
5681 break :blk slice_len;5677 break :blk slice_len;
5682 },5678 },
...@@ -5827,7 +5823,7 @@ fn airBitReverse(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5827,7 +5823,7 @@ fn airBitReverse(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5827 } else {5823 } else {
5828 var tmp = try cg.allocLocal(Type.u64);5824 var tmp = try cg.allocLocal(Type.u64);
5829 defer tmp.free(cg);5825 defer tmp.free(cg);
5830 try cg.addLabel(.local_tee, tmp.local.value);5826 try cg.addLocal(.local_tee, tmp.local.value);
5831 try cg.emitWValue(.{ .imm64 = 128 - bits });5827 try cg.emitWValue(.{ .imm64 = 128 - bits });
5832 if (ty.isSignedInt(zcu)) {5828 if (ty.isSignedInt(zcu)) {
5833 try cg.addTag(.i64_shr_s);5829 try cg.addTag(.i64_shr_s);
...@@ -5835,7 +5831,7 @@ fn airBitReverse(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5835,7 +5831,7 @@ fn airBitReverse(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5835 try cg.addTag(.i64_shr_u);5831 try cg.addTag(.i64_shr_u);
5836 }5832 }
5837 try cg.store(.stack, .stack, Type.u64, result.offset() + 8);5833 try cg.store(.stack, .stack, Type.u64, result.offset() + 8);
5838 try cg.addLabel(.local_get, tmp.local.value);5834 try cg.addLocal(.local_get, tmp.local.value);
5839 try cg.emitWValue(.{ .imm64 = bits - 64 });5835 try cg.emitWValue(.{ .imm64 = bits - 64 });
5840 try cg.addTag(.i64_shl);5836 try cg.addTag(.i64_shl);
5841 try cg.addTag(.i64_or);5837 try cg.addTag(.i64_or);
...@@ -6042,7 +6038,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6042,7 +6038,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6042 const res = try (try cg.trunc(bin_op, ty, new_ty)).toLocal(cg, ty);6038 const res = try (try cg.trunc(bin_op, ty, new_ty)).toLocal(cg, ty);
6043 const res_upcast = try cg.intcast(res, ty, new_ty);6039 const res_upcast = try cg.intcast(res, ty, new_ty);
6044 _ = try cg.cmp(res_upcast, bin_op, new_ty, .neq);6040 _ = try cg.cmp(res_upcast, bin_op, new_ty, .neq);
6045 try cg.addLabel(.local_set, overflow_bit.local.value);6041 try cg.addLocal(.local_set, overflow_bit.local.value);
6046 break :blk res;6042 break :blk res;
6047 } else if (wasm_bits == 64) blk: {6043 } else if (wasm_bits == 64) blk: {
6048 const new_ty = if (int_info.signedness == .signed) Type.i128 else Type.u128;6044 const new_ty = if (int_info.signedness == .signed) Type.i128 else Type.u128;
...@@ -6052,7 +6048,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6052,7 +6048,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6052 const res = try (try cg.trunc(bin_op, ty, new_ty)).toLocal(cg, ty);6048 const res = try (try cg.trunc(bin_op, ty, new_ty)).toLocal(cg, ty);
6053 const res_upcast = try cg.intcast(res, ty, new_ty);6049 const res_upcast = try cg.intcast(res, ty, new_ty);
6054 _ = try cg.cmp(res_upcast, bin_op, new_ty, .neq);6050 _ = try cg.cmp(res_upcast, bin_op, new_ty, .neq);
6055 try cg.addLabel(.local_set, overflow_bit.local.value);6051 try cg.addLocal(.local_set, overflow_bit.local.value);
6056 break :blk res;6052 break :blk res;
6057 } else if (int_info.bits == 128 and int_info.signedness == .unsigned) blk: {6053 } else if (int_info.bits == 128 and int_info.signedness == .unsigned) blk: {
6058 var lhs_lsb = try (try cg.load(lhs, Type.u64, 0)).toLocal(cg, Type.u64);6054 var lhs_lsb = try (try cg.load(lhs, Type.u64, 0)).toLocal(cg, Type.u64);
...@@ -6105,7 +6101,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6105,7 +6101,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
61056101
6106 // result for overflow bit6102 // result for overflow bit
6107 _ = try cg.binOp(cond_2, add_overflow, Type.bool, .@"or");6103 _ = try cg.binOp(cond_2, add_overflow, Type.bool, .@"or");
6108 try cg.addLabel(.local_set, overflow_bit.local.value);6104 try cg.addLocal(.local_set, overflow_bit.local.value);
61096105
6110 const tmp_result = try cg.allocStack(Type.u128);6106 const tmp_result = try cg.allocStack(Type.u128);
6111 try cg.emitWValue(tmp_result);6107 try cg.emitWValue(tmp_result);
...@@ -6122,7 +6118,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6122,7 +6118,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6122 &.{ lhs, rhs, overflow_ret },6118 &.{ lhs, rhs, overflow_ret },
6123 );6119 );
6124 _ = try cg.load(overflow_ret, Type.i32, 0);6120 _ = try cg.load(overflow_ret, Type.i32, 0);
6125 try cg.addLabel(.local_set, overflow_bit.local.value);6121 try cg.addLocal(.local_set, overflow_bit.local.value);
6126 break :blk res;6122 break :blk res;
6127 } else return cg.fail("TODO: @mulWithOverflow for {}", .{ty.fmt(pt)});6123 } else return cg.fail("TODO: @mulWithOverflow for {}", .{ty.fmt(pt)});
6128 var bin_op_local = try mul.toLocal(cg, ty);6124 var bin_op_local = try mul.toLocal(cg, ty);
...@@ -6543,7 +6539,7 @@ fn airDivFloor(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6543,7 +6539,7 @@ fn airDivFloor(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6543 // tee leaves the value on the stack and stores it in a local.6539 // tee leaves the value on the stack and stores it in a local.
6544 const quotient = try cg.allocLocal(ty);6540 const quotient = try cg.allocLocal(ty);
6545 _ = try cg.binOp(lhs, rhs, ty, .div);6541 _ = try cg.binOp(lhs, rhs, ty, .div);
6546 try cg.addLabel(.local_tee, quotient.local.value);6542 try cg.addLocal(.local_tee, quotient.local.value);
65476543
6548 // select takes a 32 bit value as the condition, so in the 64 bit case we use eqz to narrow6544 // select takes a 32 bit value as the condition, so in the 64 bit case we use eqz to narrow
6549 // the 64 bit value we want to use as the condition to 32 bits.6545 // the 64 bit value we want to use as the condition to 32 bits.
...@@ -6704,7 +6700,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6704,7 +6700,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
67046700
6705 var tmp = try cg.allocLocal(upcast_ty);6701 var tmp = try cg.allocLocal(upcast_ty);
6706 defer tmp.free(cg);6702 defer tmp.free(cg);
6707 try cg.addLabel(.local_set, tmp.local.value);6703 try cg.addLocal(.local_set, tmp.local.value);
67086704
6709 const imm_min: WValue = .{ .imm64 = ~@as(u64, 0) << @intCast(int_info.bits - 1) };6705 const imm_min: WValue = .{ .imm64 = ~@as(u64, 0) << @intCast(int_info.bits - 1) };
6710 try cg.emitWValue(tmp);6706 try cg.emitWValue(tmp);
...@@ -6850,13 +6846,13 @@ fn signedSat(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerErro...@@ -6850,13 +6846,13 @@ fn signedSat(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerErro
6850 try cg.emitWValue(max_wvalue);6846 try cg.emitWValue(max_wvalue);
6851 _ = try cg.cmp(bin_result, max_wvalue, ext_ty, .lt);6847 _ = try cg.cmp(bin_result, max_wvalue, ext_ty, .lt);
6852 try cg.addTag(.select);6848 try cg.addTag(.select);
6853 try cg.addLabel(.local_set, bin_result.local.value); // re-use local6849 try cg.addLocal(.local_set, bin_result.local.value); // re-use local
68546850
6855 try cg.emitWValue(bin_result);6851 try cg.emitWValue(bin_result);
6856 try cg.emitWValue(min_wvalue);6852 try cg.emitWValue(min_wvalue);
6857 _ = try cg.cmp(bin_result, min_wvalue, ext_ty, .gt);6853 _ = try cg.cmp(bin_result, min_wvalue, ext_ty, .gt);
6858 try cg.addTag(.select);6854 try cg.addTag(.select);
6859 try cg.addLabel(.local_set, bin_result.local.value); // re-use local6855 try cg.addLocal(.local_set, bin_result.local.value); // re-use local
6860 return (try cg.wrapOperand(bin_result, ty)).toLocal(cg, ty);6856 return (try cg.wrapOperand(bin_result, ty)).toLocal(cg, ty);
6861 } else {6857 } else {
6862 const zero: WValue = switch (wasm_bits) {6858 const zero: WValue = switch (wasm_bits) {
...@@ -6874,7 +6870,7 @@ fn signedSat(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerErro...@@ -6874,7 +6870,7 @@ fn signedSat(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerErro
6874 const cmp_bin_result = try cg.cmp(bin_result, lhs, ty, .lt);6870 const cmp_bin_result = try cg.cmp(bin_result, lhs, ty, .lt);
6875 _ = try cg.binOp(cmp_zero_result, cmp_bin_result, Type.u32, .xor); // comparisons always return i32, so provide u32 as type to xor.6871 _ = try cg.binOp(cmp_zero_result, cmp_bin_result, Type.u32, .xor); // comparisons always return i32, so provide u32 as type to xor.
6876 try cg.addTag(.select);6872 try cg.addTag(.select);
6877 try cg.addLabel(.local_set, bin_result.local.value); // re-use local6873 try cg.addLocal(.local_set, bin_result.local.value); // re-use local
6878 return bin_result;6874 return bin_result;
6879 }6875 }
6880}6876}
...@@ -6928,7 +6924,7 @@ fn airShlSat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6928,7 +6924,7 @@ fn airShlSat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6928 try cg.emitWValue(shl);6924 try cg.emitWValue(shl);
6929 _ = try cg.cmp(lhs, shr, ty, .neq);6925 _ = try cg.cmp(lhs, shr, ty, .neq);
6930 try cg.addTag(.select);6926 try cg.addTag(.select);
6931 try cg.addLabel(.local_set, result.local.value);6927 try cg.addLocal(.local_set, result.local.value);
6932 } else {6928 } else {
6933 const shift_size = wasm_bits - int_info.bits;6929 const shift_size = wasm_bits - int_info.bits;
6934 const shift_value: WValue = switch (wasm_bits) {6930 const shift_value: WValue = switch (wasm_bits) {
...@@ -6973,12 +6969,12 @@ fn airShlSat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6973,12 +6969,12 @@ fn airShlSat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6973 try cg.emitWValue(shl);6969 try cg.emitWValue(shl);
6974 _ = try cg.cmp(shl_res, shr, ext_ty, .neq);6970 _ = try cg.cmp(shl_res, shr, ext_ty, .neq);
6975 try cg.addTag(.select);6971 try cg.addTag(.select);
6976 try cg.addLabel(.local_set, result.local.value);6972 try cg.addLocal(.local_set, result.local.value);
6977 var shift_result = try cg.binOp(result, shift_value, ext_ty, .shr);6973 var shift_result = try cg.binOp(result, shift_value, ext_ty, .shr);
6978 if (is_signed) {6974 if (is_signed) {
6979 shift_result = try cg.wrapOperand(shift_result, ty);6975 shift_result = try cg.wrapOperand(shift_result, ty);
6980 }6976 }
6981 try cg.addLabel(.local_set, result.local.value);6977 try cg.addLocal(.local_set, result.local.value);
6982 }6978 }
69836979
6984 return cg.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });6980 return cg.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
...@@ -7114,13 +7110,13 @@ fn airErrorSetHasValue(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7114,13 +7110,13 @@ fn airErrorSetHasValue(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7114 // 'false' branch (i.e. error set does not have value7110 // 'false' branch (i.e. error set does not have value
7115 // ensure we set local to 0 in case the local was re-used.7111 // ensure we set local to 0 in case the local was re-used.
7116 try cg.addImm32(0);7112 try cg.addImm32(0);
7117 try cg.addLabel(.local_set, result.local.value);7113 try cg.addLocal(.local_set, result.local.value);
7118 try cg.addLabel(.br, 1);7114 try cg.addLabel(.br, 1);
7119 try cg.endBlock();7115 try cg.endBlock();
71207116
7121 // 'true' branch7117 // 'true' branch
7122 try cg.addImm32(1);7118 try cg.addImm32(1);
7123 try cg.addLabel(.local_set, result.local.value);7119 try cg.addLocal(.local_set, result.local.value);
7124 try cg.addLabel(.br, 0);7120 try cg.addLabel(.br, 0);
7125 try cg.endBlock();7121 try cg.endBlock();
71267122
...@@ -7161,9 +7157,9 @@ fn airCmpxchg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7161,9 +7157,9 @@ fn airCmpxchg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7161 .offset = ptr_operand.offset(),7157 .offset = ptr_operand.offset(),
7162 .alignment = @intCast(ty.abiAlignment(zcu).toByteUnits().?),7158 .alignment = @intCast(ty.abiAlignment(zcu).toByteUnits().?),
7163 });7159 });
7164 try cg.addLabel(.local_tee, val_local.local.value);7160 try cg.addLocal(.local_tee, val_local.local.value);
7165 _ = try cg.cmp(.stack, expected_val, ty, .eq);7161 _ = try cg.cmp(.stack, expected_val, ty, .eq);
7166 try cg.addLabel(.local_set, cmp_result.local.value);7162 try cg.addLocal(.local_set, cmp_result.local.value);
7167 break :val val_local;7163 break :val val_local;
7168 } else val: {7164 } else val: {
7169 if (ty.abiSize(zcu) > 8) {7165 if (ty.abiSize(zcu) > 8) {
...@@ -7175,7 +7171,7 @@ fn airCmpxchg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7175,7 +7171,7 @@ fn airCmpxchg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7175 try cg.lowerToStack(new_val);7171 try cg.lowerToStack(new_val);
7176 try cg.emitWValue(ptr_val);7172 try cg.emitWValue(ptr_val);
7177 _ = try cg.cmp(ptr_val, expected_val, ty, .eq);7173 _ = try cg.cmp(ptr_val, expected_val, ty, .eq);
7178 try cg.addLabel(.local_tee, cmp_result.local.value);7174 try cg.addLocal(.local_tee, cmp_result.local.value);
7179 try cg.addTag(.select);7175 try cg.addTag(.select);
7180 try cg.store(.stack, .stack, ty, 0);7176 try cg.store(.stack, .stack, ty, 0);
71817177
...@@ -7285,11 +7281,11 @@ fn airAtomicRmw(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7285,11 +7281,11 @@ fn airAtomicRmw(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7285 },7281 },
7286 );7282 );
7287 const select_res = try cg.allocLocal(ty);7283 const select_res = try cg.allocLocal(ty);
7288 try cg.addLabel(.local_tee, select_res.local.value);7284 try cg.addLocal(.local_tee, select_res.local.value);
7289 _ = try cg.cmp(.stack, value, ty, .neq); // leave on stack so we can use it for br_if7285 _ = try cg.cmp(.stack, value, ty, .neq); // leave on stack so we can use it for br_if
72907286
7291 try cg.emitWValue(select_res);7287 try cg.emitWValue(select_res);
7292 try cg.addLabel(.local_set, value.local.value);7288 try cg.addLocal(.local_set, value.local.value);
72937289
7294 try cg.addLabel(.br_if, 0);7290 try cg.addLabel(.br_if, 0);
7295 try cg.endBlock();7291 try cg.endBlock();