| ... | @@ -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, |
| 326 | | 320 | |
| ... | @@ -681,13 +675,11 @@ test "Wasm - buildOpcode" { | ... | @@ -681,13 +675,11 @@ test "Wasm - buildOpcode" { |
| 681 | // Make sure buildOpcode is referenced, and test some examples | 675 | // 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 }); |
| 687 | | 680 | |
| 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 | } |
| 878 | | 870 | |
| | 871 | fn 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 to | 875 | /// Accepts an unsigned 32bit integer rather than a signed integer to |
| 880 | /// prevent us from having to bitcast multiple times as most values | 876 | /// 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-op | 1013 | .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 offset | 1062 | .stack_offset => try cg.addLocal(.local_get, cg.bottom_stack_value.local.value), // caller must ensure to address the offset |
| 1067 | } | 1063 | } |
| 1068 | } | 1064 | } |
| 1069 | | 1065 | |
| ... | @@ -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); |
| 1628 | | 1624 | |
| 1629 | // outer block to jump to when loop is done | 1625 | // 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 loop | 1682 | try cg.addLabel(.br, 0); // jump to start of loop |
| 1687 | } | 1683 | } |
| 1688 | try cg.endBlock(); // close off loop block | 1684 | 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 | } |
| 1807 | | 1803 | |
| ... | @@ -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 optimize | 2224 | // 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 { |
| 2817 | | 2813 | |
| 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); |
| 2821 | | 2817 | |
| 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 { |
| 2833 | | 2829 | |
| 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); |
| 2837 | | 2833 | |
| 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 { |
| 2852 | | 2848 | |
| 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); |
| 3591 | | 3587 | |
| 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 | } |
| 3596 | | 3592 | |
| ... | @@ -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); |
| 4809 | | 4805 | |
| 4810 | // outer block to jump to when loop is done | 4806 | // 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); |
| 4839 | | 4835 | |
| 4840 | // end of loop | 4836 | // end of loop |
| 4841 | try cg.addLabel(.br, 0); // jump to start of loop | 4837 | 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 | else | 5213 | 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); |
| 5220 | | 5216 | |
| 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); |
| 5400 | | 5396 | |
| 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(); |
| 5404 | | 5400 | |
| 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 { |
| 5642 | | 5638 | |
| 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); |
| 5651 | | 5647 | |
| ... | @@ -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 { |
| 6105 | | 6101 | |
| 6106 | // result for overflow bit | 6102 | // 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); |
| 6109 | | 6105 | |
| 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); |
| 6547 | | 6543 | |
| 6548 | // select takes a 32 bit value as the condition, so in the 64 bit case we use eqz to narrow | 6544 | // 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 { |
| 6704 | | 6700 | |
| 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); |
| 6708 | | 6704 | |
| 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 local | 6849 | try cg.addLocal(.local_set, bin_result.local.value); // re-use local |
| 6854 | | 6850 | |
| 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 local | 6855 | 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 local | 6873 | 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 | } |
| 6983 | | 6979 | |
| 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 value | 7110 | // '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(); |
| 7120 | | 7116 | |
| 7121 | // 'true' branch | 7117 | // '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(); |
| 7126 | | 7122 | |
| ... | @@ -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); |
| 7181 | | 7177 | |
| ... | @@ -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_if | 7285 | _ = try cg.cmp(.stack, value, ty, .neq); // leave on stack so we can use it for br_if |
| 7290 | | 7286 | |
| 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); |
| 7293 | | 7289 | |
| 7294 | try cg.addLabel(.br_if, 0); | 7290 | try cg.addLabel(.br_if, 0); |
| 7295 | try cg.endBlock(); | 7291 | try cg.endBlock(); |