authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-19 03:51:51-04:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-21 08:49:54+01:00
log24f0900ecba3ea67b7c6df31836ed40de22b7ab8
treec0fa927b4d9e7e598e1793a857313b39c9488cf8
parentbbd05e2d972b26038bf307f03aa569a7e7a2ac2c

x86_64: implement some error union ops


2 files changed, 101 insertions(+), 21 deletions(-)

src/arch/x86_64/CodeGen.zig+101-20
...@@ -994,10 +994,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -994,10 +994,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
994 .optional_payload => try self.airOptionalPayload(inst),994 .optional_payload => try self.airOptionalPayload(inst),
995 .optional_payload_ptr => try self.airOptionalPayloadPtr(inst),995 .optional_payload_ptr => try self.airOptionalPayloadPtr(inst),
996 .optional_payload_ptr_set => try self.airOptionalPayloadPtrSet(inst),996 .optional_payload_ptr_set => try self.airOptionalPayloadPtrSet(inst),
997 .unwrap_errunion_err => try self.airUnwrapErrErr(inst),997 .unwrap_errunion_err => try self.airUnwrapErrUnionErr(inst),
998 .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst),998 .unwrap_errunion_payload => try self.airUnwrapErrUnionPayload(inst),
999 .unwrap_errunion_err_ptr => try self.airUnwrapErrErrPtr(inst),999 .unwrap_errunion_err_ptr => try self.airUnwrapErrUnionErrPtr(inst),
1000 .unwrap_errunion_payload_ptr=> try self.airUnwrapErrPayloadPtr(inst),1000 .unwrap_errunion_payload_ptr=> try self.airUnwrapErrUnionPayloadPtr(inst),
1001 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),1001 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
1002 .err_return_trace => try self.airErrReturnTrace(inst),1002 .err_return_trace => try self.airErrReturnTrace(inst),
1003 .set_err_return_trace => try self.airSetErrReturnTrace(inst),1003 .set_err_return_trace => try self.airSetErrReturnTrace(inst),
...@@ -1923,7 +1923,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -1923,7 +1923,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
1923 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1923 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1924}1924}
19251925
1926fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {1926fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
1927 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1927 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1928 if (self.liveness.isUnused(inst)) {1928 if (self.liveness.isUnused(inst)) {
1929 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });1929 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
...@@ -1967,7 +1967,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1967,7 +1967,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
1967 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1967 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1968}1968}
19691969
1970fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {1970fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
1971 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1971 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1972 if (self.liveness.isUnused(inst)) {1972 if (self.liveness.isUnused(inst)) {
1973 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });1973 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
...@@ -2021,31 +2021,112 @@ fn genUnwrapErrorUnionPayloadMir(...@@ -2021,31 +2021,112 @@ fn genUnwrapErrorUnionPayloadMir(
2021}2021}
20222022
2023// *(E!T) -> E2023// *(E!T) -> E
2024fn airUnwrapErrErrPtr(self: *Self, inst: Air.Inst.Index) !void {2024fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
2025 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2025 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2026 const result: MCValue = if (self.liveness.isUnused(inst))2026 const result: MCValue = result: {
2027 .dead2027 if (self.liveness.isUnused(inst)) break :result .dead;
2028 else2028
2029 return self.fail("TODO implement unwrap error union error ptr for {}", .{self.target.cpu.arch});2029 const src_ty = self.air.typeOf(ty_op.operand);
2030 const src_mcv = try self.resolveInst(ty_op.operand);
2031 const src_reg = switch (src_mcv) {
2032 .register => |reg| reg,
2033 else => try self.copyToTmpRegister(src_ty, src_mcv),
2034 };
2035 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
2036 defer self.register_manager.unlockReg(src_lock);
2037
2038 const dst_reg = try self.register_manager.allocReg(inst, gp);
2039 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
2040 defer self.register_manager.unlockReg(dst_lock);
2041
2042 const eu_ty = src_ty.childType();
2043 const pl_ty = eu_ty.errorUnionPayload();
2044 const err_ty = eu_ty.errorUnionSet();
2045 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));
2046 const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
2047 try self.asmRegisterMemory(
2048 .mov,
2049 registerAlias(dst_reg, err_abi_size),
2050 Memory.sib(Memory.PtrSize.fromSize(err_abi_size), .{ .base = src_reg, .disp = err_off }),
2051 );
2052 break :result .{ .register = dst_reg };
2053 };
2030 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2054 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2031}2055}
20322056
2033// *(E!T) -> *T2057// *(E!T) -> *T
2034fn airUnwrapErrPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {2058fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
2035 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2059 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2036 const result: MCValue = if (self.liveness.isUnused(inst))2060 const result: MCValue = result: {
2037 .dead2061 if (self.liveness.isUnused(inst)) break :result .dead;
2038 else2062
2039 return self.fail("TODO implement unwrap error union payload ptr for {}", .{self.target.cpu.arch});2063 const src_ty = self.air.typeOf(ty_op.operand);
2064 const src_mcv = try self.resolveInst(ty_op.operand);
2065 const src_reg = switch (src_mcv) {
2066 .register => |reg| reg,
2067 else => try self.copyToTmpRegister(src_ty, src_mcv),
2068 };
2069 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
2070 defer self.register_manager.unlockReg(src_lock);
2071
2072 const dst_ty = self.air.typeOfIndex(inst);
2073 const dst_reg = try self.register_manager.allocReg(inst, gp);
2074 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
2075 defer self.register_manager.unlockReg(dst_lock);
2076
2077 const eu_ty = src_ty.childType();
2078 const pl_ty = eu_ty.errorUnionPayload();
2079 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*));
2080 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
2081 try self.asmRegisterMemory(
2082 .lea,
2083 registerAlias(dst_reg, dst_abi_size),
2084 Memory.sib(.qword, .{ .base = src_reg, .disp = pl_off }),
2085 );
2086 break :result .{ .register = dst_reg };
2087 };
2040 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2088 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2041}2089}
20422090
2043fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {2091fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
2044 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2092 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2045 const result: MCValue = if (self.liveness.isUnused(inst))2093 const result: MCValue = result: {
2046 .dead2094 const src_ty = self.air.typeOf(ty_op.operand);
2047 else2095 const src_mcv = try self.resolveInst(ty_op.operand);
2048 return self.fail("TODO implement .errunion_payload_ptr_set for {}", .{self.target.cpu.arch});2096 const src_reg = switch (src_mcv) {
2097 .register => |reg| reg,
2098 else => try self.copyToTmpRegister(src_ty, src_mcv),
2099 };
2100 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
2101 defer self.register_manager.unlockReg(src_lock);
2102
2103 const eu_ty = src_ty.childType();
2104 const pl_ty = eu_ty.errorUnionPayload();
2105 const err_ty = eu_ty.errorUnionSet();
2106 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));
2107 const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
2108 try self.asmMemoryImmediate(
2109 .mov,
2110 Memory.sib(Memory.PtrSize.fromSize(err_abi_size), .{ .base = src_reg, .disp = err_off }),
2111 Immediate.u(0),
2112 );
2113
2114 if (self.liveness.isUnused(inst)) break :result .dead;
2115
2116 const dst_ty = self.air.typeOfIndex(inst);
2117 const dst_reg = try self.register_manager.allocReg(inst, gp);
2118 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
2119 defer self.register_manager.unlockReg(dst_lock);
2120
2121 const pl_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));
2122 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
2123 try self.asmRegisterMemory(
2124 .lea,
2125 registerAlias(dst_reg, dst_abi_size),
2126 Memory.sib(.qword, .{ .base = src_reg, .disp = pl_off }),
2127 );
2128 break :result .{ .register = dst_reg };
2129 };
2049 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2130 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2050}2131}
20512132
test/behavior/error.zig-1
...@@ -731,7 +731,6 @@ test "pointer to error union payload" {...@@ -731,7 +731,6 @@ test "pointer to error union payload" {
731 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO731 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
732 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO732 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
733 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO733 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
734 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
735 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO734 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
736735
737 var err_union: anyerror!u8 = 15;736 var err_union: anyerror!u8 = 15;