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 {
994994 .optional_payload => try self.airOptionalPayload(inst),
995995 .optional_payload_ptr => try self.airOptionalPayloadPtr(inst),
996996 .optional_payload_ptr_set => try self.airOptionalPayloadPtrSet(inst),
997 .unwrap_errunion_err => try self.airUnwrapErrErr(inst),
998 .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst),
999 .unwrap_errunion_err_ptr => try self.airUnwrapErrErrPtr(inst),
1000 .unwrap_errunion_payload_ptr=> try self.airUnwrapErrPayloadPtr(inst),
997 .unwrap_errunion_err => try self.airUnwrapErrUnionErr(inst),
998 .unwrap_errunion_payload => try self.airUnwrapErrUnionPayload(inst),
999 .unwrap_errunion_err_ptr => try self.airUnwrapErrUnionErrPtr(inst),
1000 .unwrap_errunion_payload_ptr=> try self.airUnwrapErrUnionPayloadPtr(inst),
10011001 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
10021002 .err_return_trace => try self.airErrReturnTrace(inst),
10031003 .set_err_return_trace => try self.airSetErrReturnTrace(inst),
......@@ -1923,7 +1923,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
19231923 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
19241924}
19251925
1926fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
1926fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
19271927 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
19281928 if (self.liveness.isUnused(inst)) {
19291929 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
......@@ -1967,7 +1967,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
19671967 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
19681968}
19691969
1970fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
1970fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
19711971 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
19721972 if (self.liveness.isUnused(inst)) {
19731973 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
......@@ -2021,31 +2021,112 @@ fn genUnwrapErrorUnionPayloadMir(
20212021}
20222022
20232023// *(E!T) -> E
2024fn airUnwrapErrErrPtr(self: *Self, inst: Air.Inst.Index) !void {
2024fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
20252025 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2026 const result: MCValue = if (self.liveness.isUnused(inst))
2027 .dead
2028 else
2029 return self.fail("TODO implement unwrap error union error ptr for {}", .{self.target.cpu.arch});
2026 const result: MCValue = result: {
2027 if (self.liveness.isUnused(inst)) break :result .dead;
2028
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 };
20302054 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
20312055}
20322056
20332057// *(E!T) -> *T
2034fn airUnwrapErrPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
2058fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
20352059 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2036 const result: MCValue = if (self.liveness.isUnused(inst))
2037 .dead
2038 else
2039 return self.fail("TODO implement unwrap error union payload ptr for {}", .{self.target.cpu.arch});
2060 const result: MCValue = result: {
2061 if (self.liveness.isUnused(inst)) break :result .dead;
2062
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 };
20402088 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
20412089}
20422090
20432091fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
20442092 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2045 const result: MCValue = if (self.liveness.isUnused(inst))
2046 .dead
2047 else
2048 return self.fail("TODO implement .errunion_payload_ptr_set for {}", .{self.target.cpu.arch});
2093 const result: MCValue = result: {
2094 const src_ty = self.air.typeOf(ty_op.operand);
2095 const src_mcv = try self.resolveInst(ty_op.operand);
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 };
20492130 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
20502131}
20512132
test/behavior/error.zig-1
......@@ -731,7 +731,6 @@ test "pointer to error union payload" {
731731 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
732732 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
733733 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
734 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
735734 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
736735
737736 var err_union: anyerror!u8 = 15;