| ... | ... | @@ -994,10 +994,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 994 | 994 | .optional_payload => try self.airOptionalPayload(inst), |
| 995 | 995 | .optional_payload_ptr => try self.airOptionalPayloadPtr(inst), |
| 996 | 996 | .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), |
| 1001 | 1001 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), |
| 1002 | 1002 | .err_return_trace => try self.airErrReturnTrace(inst), |
| 1003 | 1003 | .set_err_return_trace => try self.airSetErrReturnTrace(inst), |
| ... | ... | @@ -1923,7 +1923,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 1923 | 1923 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1924 | 1924 | } |
| 1925 | 1925 | |
| 1926 | | fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1926 | fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1927 | 1927 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1928 | 1928 | if (self.liveness.isUnused(inst)) { |
| 1929 | 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 | 1967 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1968 | 1968 | } |
| 1969 | 1969 | |
| 1970 | | fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1970 | fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1971 | 1971 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1972 | 1972 | if (self.liveness.isUnused(inst)) { |
| 1973 | 1973 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| ... | ... | @@ -2021,31 +2021,112 @@ fn genUnwrapErrorUnionPayloadMir( |
| 2021 | 2021 | } |
| 2022 | 2022 | |
| 2023 | 2023 | // *(E!T) -> E |
| 2024 | | fn airUnwrapErrErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 2024 | fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 2025 | 2025 | 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 | }; |
| 2030 | 2054 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2031 | 2055 | } |
| 2032 | 2056 | |
| 2033 | 2057 | // *(E!T) -> *T |
| 2034 | | fn airUnwrapErrPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 2058 | fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 2035 | 2059 | 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 | }; |
| 2040 | 2088 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2041 | 2089 | } |
| 2042 | 2090 | |
| 2043 | 2091 | fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 2044 | 2092 | 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 | }; |
| 2049 | 2130 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2050 | 2131 | } |
| 2051 | 2132 | |