authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-28 17:48:38+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-28 23:20:05+01:00
log05431d7c4a8cb20a3a70553ef0d0f8ed00a05402
tree39b2c28cad28f68af5c92a9e3ede7284110faeb2
parenta7ca40b2817dbf3f2085141f32f20f431707391b

x64: impl unwrap_errunion_payload and unwrap_errunion_err for register


2 files changed, 44 insertions(+), 26 deletions(-)

src/arch/x86_64/CodeGen.zig+44-22
......@@ -1738,14 +1738,22 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
17381738 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
17391739 }
17401740 const err_union_ty = self.air.typeOf(ty_op.operand);
1741 const err_ty = err_union_ty.errorUnionSet();
17411742 const payload_ty = err_union_ty.errorUnionPayload();
17421743 const operand = try self.resolveInst(ty_op.operand);
1744 operand.freezeIfRegister(&self.register_manager);
1745 defer operand.unfreezeIfRegister(&self.register_manager);
1746
17431747 const result: MCValue = result: {
17441748 if (!payload_ty.hasRuntimeBits()) break :result operand;
17451749 switch (operand) {
17461750 .stack_offset => |off| {
17471751 break :result MCValue{ .stack_offset = off };
17481752 },
1753 .register => {
1754 // TODO reuse operand
1755 break :result try self.copyToRegisterWithInstTracking(inst, err_ty, operand);
1756 },
17491757 else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}),
17501758 }
17511759 };
......@@ -1763,13 +1771,24 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
17631771 if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;
17641772
17651773 const operand = try self.resolveInst(ty_op.operand);
1774 operand.freezeIfRegister(&self.register_manager);
1775 defer operand.unfreezeIfRegister(&self.register_manager);
1776
17661777 const err_ty = err_union_ty.errorUnionSet();
1767 const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
17681778 switch (operand) {
17691779 .stack_offset => |off| {
1780 const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
17701781 const offset = off - @intCast(i32, err_abi_size);
17711782 break :result MCValue{ .stack_offset = offset };
17721783 },
1784 .register => {
1785 // TODO reuse operand
1786 const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand);
1787 try self.shiftRegister(result.register.to64(), @intCast(u6, err_ty.bitSize(self.target.*)));
1788 break :result MCValue{
1789 .register = registerAlias(result.register, @intCast(u32, payload_ty.abiSize(self.target.*))),
1790 };
1791 },
17731792 else => return self.fail("TODO implement unwrap_err_payload for {}", .{operand}),
17741793 }
17751794 };
......@@ -2686,27 +2705,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
26862705 };
26872706
26882707 // Shift by struct_field_offset.
2689 const shift_amount = @intCast(u8, struct_field_offset * 8);
2690 if (shift_amount > 0) {
2691 if (shift_amount == 1) {
2692 _ = try self.addInst(.{
2693 .tag = .shr,
2694 .ops = (Mir.Ops{
2695 .reg1 = dst_mcv.register,
2696 }).encode(),
2697 .data = undefined,
2698 });
2699 } else {
2700 _ = try self.addInst(.{
2701 .tag = .shr,
2702 .ops = (Mir.Ops{
2703 .reg1 = dst_mcv.register,
2704 .flags = 0b10,
2705 }).encode(),
2706 .data = .{ .imm = shift_amount },
2707 });
2708 }
2709 }
2708 const shift = @intCast(u8, struct_field_offset * 8);
2709 try self.shiftRegister(dst_mcv.register, shift);
27102710
27112711 // Mask with reg.size() - struct_field_size
27122712 const mask_shift = @intCast(u6, (64 - struct_field_ty.bitSize(self.target.*)));
......@@ -5768,3 +5768,25 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {
57685768 unreachable; // TODO handle floating-point registers
57695769 }
57705770}
5771
5772fn shiftRegister(self: *Self, reg: Register, shift: u8) !void {
5773 if (shift == 0) return;
5774 if (shift == 1) {
5775 _ = try self.addInst(.{
5776 .tag = .shr,
5777 .ops = (Mir.Ops{
5778 .reg1 = reg,
5779 }).encode(),
5780 .data = undefined,
5781 });
5782 } else {
5783 _ = try self.addInst(.{
5784 .tag = .shr,
5785 .ops = (Mir.Ops{
5786 .reg1 = reg,
5787 .flags = 0b10,
5788 }).encode(),
5789 .data = .{ .imm = shift },
5790 });
5791 }
5792}
test/behavior/error.zig-4
......@@ -78,7 +78,6 @@ fn unwrapSimpleValueFromErrorDo() anyerror!isize {
7878}
7979
8080test "error return in assignment" {
81 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
8281 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8382 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
8483
......@@ -121,7 +120,6 @@ test "widen cast integer payload of error union function call" {
121120}
122121
123122test "debug info for optional error set" {
124 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
125123 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
126124 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
127125
......@@ -173,7 +171,6 @@ fn bar2() (error{}!void) {}
173171test "error union type " {
174172 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
175173 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
176 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
177174 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
178175
179176 try testErrorUnionType();
......@@ -191,7 +188,6 @@ fn testErrorUnionType() !void {
191188test "error set type" {
192189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
193190 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
194 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
195191 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
196192
197193 try testErrorSetType();