| ... | @@ -681,8 +681,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -681,8 +681,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 681 | .prefetch => try self.airPrefetch(inst), | 681 | .prefetch => try self.airPrefetch(inst), |
| 682 | .mul_add => try self.airMulAdd(inst), | 682 | .mul_add => try self.airMulAdd(inst), |
| 683 | | 683 | |
| 684 | .@"try" => @panic("TODO"), | 684 | .@"try" => try self.airTry(inst), |
| 685 | .try_ptr => @panic("TODO"), | 685 | .try_ptr => try self.airTryPtr(inst), |
| 686 | | 686 | |
| 687 | .dbg_var_ptr, | 687 | .dbg_var_ptr, |
| 688 | .dbg_var_val, | 688 | .dbg_var_val, |
| ... | @@ -1807,14 +1807,24 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1807,14 +1807,24 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1807 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); | 1807 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 1808 | } | 1808 | } |
| 1809 | const err_union_ty = self.air.typeOf(ty_op.operand); | 1809 | const err_union_ty = self.air.typeOf(ty_op.operand); |
| | 1810 | const operand = try self.resolveInst(ty_op.operand); |
| | 1811 | const result = try self.genUnwrapErrorUnionPayloadMir(inst, err_union_ty, operand); |
| | 1812 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| | 1813 | } |
| | 1814 | |
| | 1815 | fn genUnwrapErrorUnionPayloadMir( |
| | 1816 | self: *Self, |
| | 1817 | maybe_inst: ?Air.Inst.Index, |
| | 1818 | err_union_ty: Type, |
| | 1819 | err_union: MCValue, |
| | 1820 | ) !MCValue { |
| 1810 | const payload_ty = err_union_ty.errorUnionPayload(); | 1821 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 1811 | const err_ty = err_union_ty.errorUnionSet(); | 1822 | const err_ty = err_union_ty.errorUnionSet(); |
| 1812 | const operand = try self.resolveInst(ty_op.operand); | | |
| 1813 | | 1823 | |
| 1814 | const result: MCValue = result: { | 1824 | const result: MCValue = result: { |
| 1815 | if (err_ty.errorSetCardinality() == .zero) { | 1825 | if (err_ty.errorSetCardinality() == .zero) { |
| 1816 | // TODO check if we can reuse | 1826 | // TODO check if we can reuse |
| 1817 | break :result operand; | 1827 | break :result err_union; |
| 1818 | } | 1828 | } |
| 1819 | | 1829 | |
| 1820 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 1830 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| ... | @@ -1822,7 +1832,7 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1822,7 +1832,7 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1822 | } | 1832 | } |
| 1823 | | 1833 | |
| 1824 | const payload_off = errUnionPayloadOffset(payload_ty, self.target.*); | 1834 | const payload_off = errUnionPayloadOffset(payload_ty, self.target.*); |
| 1825 | switch (operand) { | 1835 | switch (err_union) { |
| 1826 | .stack_offset => |off| { | 1836 | .stack_offset => |off| { |
| 1827 | const offset = off - @intCast(i32, payload_off); | 1837 | const offset = off - @intCast(i32, payload_off); |
| 1828 | break :result MCValue{ .stack_offset = offset }; | 1838 | break :result MCValue{ .stack_offset = offset }; |
| ... | @@ -1831,19 +1841,23 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1831,19 +1841,23 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1831 | // TODO reuse operand | 1841 | // TODO reuse operand |
| 1832 | const lock = self.register_manager.lockRegAssumeUnused(reg); | 1842 | const lock = self.register_manager.lockRegAssumeUnused(reg); |
| 1833 | defer self.register_manager.unlockReg(lock); | 1843 | defer self.register_manager.unlockReg(lock); |
| 1834 | const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand); | 1844 | const result_reg: Register = if (maybe_inst) |inst| |
| | 1845 | (try self.copyToRegisterWithInstTracking(inst, err_union_ty, err_union)).register |
| | 1846 | else |
| | 1847 | try self.copyToTmpRegister(err_union_ty, err_union); |
| 1835 | if (payload_off > 0) { | 1848 | if (payload_off > 0) { |
| 1836 | const shift = @intCast(u6, payload_off * 8); | 1849 | const shift = @intCast(u6, payload_off * 8); |
| 1837 | try self.genShiftBinOpMir(.shr, err_union_ty, result.register, .{ .immediate = shift }); | 1850 | try self.genShiftBinOpMir(.shr, err_union_ty, result_reg, .{ .immediate = shift }); |
| 1838 | } else { | 1851 | } else { |
| 1839 | try self.truncateRegister(payload_ty, result.register); | 1852 | try self.truncateRegister(payload_ty, result_reg); |
| 1840 | } | 1853 | } |
| 1841 | break :result result; | 1854 | break :result MCValue{ .register = result_reg }; |
| 1842 | }, | 1855 | }, |
| 1843 | else => return self.fail("TODO implement unwrap_err_payload for {}", .{operand}), | 1856 | else => return self.fail("TODO implement genUnwrapErrorUnionPayloadMir for {}", .{err_union}), |
| 1844 | } | 1857 | } |
| 1845 | }; | 1858 | }; |
| 1846 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1859 | |
| | 1860 | return result; |
| 1847 | } | 1861 | } |
| 1848 | | 1862 | |
| 1849 | // *(E!T) -> E | 1863 | // *(E!T) -> E |
| ... | @@ -4231,6 +4245,45 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4231,6 +4245,45 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { |
| 4231 | return self.finishAir(inst, result, .{ un_op, .none, .none }); | 4245 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4232 | } | 4246 | } |
| 4233 | | 4247 | |
| | 4248 | fn airTry(self: *Self, inst: Air.Inst.Index) !void { |
| | 4249 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| | 4250 | const extra = self.air.extraData(Air.Try, pl_op.payload); |
| | 4251 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| | 4252 | const err_union_ty = self.air.typeOf(pl_op.operand); |
| | 4253 | const err_union = try self.resolveInst(pl_op.operand); |
| | 4254 | const result = try self.genTry(inst, err_union, body, err_union_ty, false); |
| | 4255 | return self.finishAir(inst, result, .{ pl_op.operand, .none, .none }); |
| | 4256 | } |
| | 4257 | |
| | 4258 | fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { |
| | 4259 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| | 4260 | const extra = self.air.extraData(Air.TryPtr, ty_pl.payload); |
| | 4261 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| | 4262 | const err_union_ty = self.air.typeOf(extra.data.ptr).childType(); |
| | 4263 | const err_union_ptr = try self.resolveInst(extra.data.ptr); |
| | 4264 | const result = try self.genTry(inst, err_union_ptr, body, err_union_ty, true); |
| | 4265 | return self.finishAir(inst, result, .{ extra.data.ptr, .none, .none }); |
| | 4266 | } |
| | 4267 | |
| | 4268 | fn genTry( |
| | 4269 | self: *Self, |
| | 4270 | inst: Air.Inst.Index, |
| | 4271 | err_union: MCValue, |
| | 4272 | body: []const Air.Inst.Index, |
| | 4273 | err_union_ty: Type, |
| | 4274 | operand_is_ptr: bool, |
| | 4275 | ) !MCValue { |
| | 4276 | if (operand_is_ptr) { |
| | 4277 | return self.fail("TODO genTry for pointers", .{}); |
| | 4278 | } |
| | 4279 | const is_err_mcv = try self.isErr(null, err_union_ty, err_union); |
| | 4280 | const reloc = try self.genCondBrMir(Type.anyerror, is_err_mcv); |
| | 4281 | try self.genBody(body); |
| | 4282 | try self.performReloc(reloc); |
| | 4283 | const result = try self.genUnwrapErrorUnionPayloadMir(inst, err_union_ty, err_union); |
| | 4284 | return result; |
| | 4285 | } |
| | 4286 | |
| 4234 | fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { | 4287 | fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { |
| 4235 | const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt; | 4288 | const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt; |
| 4236 | const payload = try self.addExtra(Mir.DbgLineColumn{ | 4289 | const payload = try self.addExtra(Mir.DbgLineColumn{ |
| ... | @@ -4596,7 +4649,7 @@ fn isNonNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCV | ... | @@ -4596,7 +4649,7 @@ fn isNonNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCV |
| 4596 | return MCValue{ .eflags = is_null_res.eflags.negate() }; | 4649 | return MCValue{ .eflags = is_null_res.eflags.negate() }; |
| 4597 | } | 4650 | } |
| 4598 | | 4651 | |
| 4599 | fn isErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue { | 4652 | fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !MCValue { |
| 4600 | const err_type = ty.errorUnionSet(); | 4653 | const err_type = ty.errorUnionSet(); |
| 4601 | | 4654 | |
| 4602 | if (err_type.errorSetCardinality() == .zero) { | 4655 | if (err_type.errorSetCardinality() == .zero) { |
| ... | @@ -4604,7 +4657,9 @@ fn isErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue | ... | @@ -4604,7 +4657,9 @@ fn isErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue |
| 4604 | } | 4657 | } |
| 4605 | | 4658 | |
| 4606 | try self.spillEflagsIfOccupied(); | 4659 | try self.spillEflagsIfOccupied(); |
| 4607 | self.eflags_inst = inst; | 4660 | if (maybe_inst) |inst| { |
| | 4661 | self.eflags_inst = inst; |
| | 4662 | } |
| 4608 | | 4663 | |
| 4609 | const err_off = errUnionErrorOffset(ty.errorUnionPayload(), self.target.*); | 4664 | const err_off = errUnionErrorOffset(ty.errorUnionPayload(), self.target.*); |
| 4610 | switch (operand) { | 4665 | switch (operand) { |