| ... | ... | @@ -13,6 +13,7 @@ const link = @import("../../link.zig"); |
| 13 | 13 | const Module = @import("../../Module.zig"); |
| 14 | 14 | const TypedValue = @import("../../TypedValue.zig"); |
| 15 | 15 | const ErrorMsg = Module.ErrorMsg; |
| 16 | const codegen = @import("../../codegen.zig"); |
| 16 | 17 | const Air = @import("../../Air.zig"); |
| 17 | 18 | const Mir = @import("Mir.zig"); |
| 18 | 19 | const Emit = @import("Emit.zig"); |
| ... | ... | @@ -26,6 +27,8 @@ const build_options = @import("build_options"); |
| 26 | 27 | |
| 27 | 28 | const bits = @import("bits.zig"); |
| 28 | 29 | const abi = @import("abi.zig"); |
| 30 | const errUnionPayloadOffset = codegen.errUnionPayloadOffset; |
| 31 | const errUnionErrorOffset = codegen.errUnionErrorOffset; |
| 29 | 32 | const Instruction = bits.Instruction; |
| 30 | 33 | const ShiftWidth = Instruction.ShiftWidth; |
| 31 | 34 | const RegisterManager = abi.RegisterManager; |
| ... | ... | @@ -627,7 +630,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 627 | 630 | .prefetch => @panic("TODO try self.airPrefetch(inst)"), |
| 628 | 631 | .mul_add => @panic("TODO try self.airMulAdd(inst)"), |
| 629 | 632 | |
| 630 | | .@"try" => @panic("TODO try self.airTry(inst)"), |
| 633 | .@"try" => try self.airTry(inst), |
| 631 | 634 | .try_ptr => @panic("TODO try self.airTryPtr(inst)"), |
| 632 | 635 | |
| 633 | 636 | .dbg_var_ptr, |
| ... | ... | @@ -1796,6 +1799,24 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void { |
| 1796 | 1799 | return self.fail("TODO implement switch for {}", .{self.target.cpu.arch}); |
| 1797 | 1800 | } |
| 1798 | 1801 | |
| 1802 | fn airTry(self: *Self, inst: Air.Inst.Index) !void { |
| 1803 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 1804 | const extra = self.air.extraData(Air.Try, pl_op.payload); |
| 1805 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| 1806 | const result: MCValue = result: { |
| 1807 | const error_union_ty = self.air.typeOf(pl_op.operand); |
| 1808 | const error_union = try self.resolveInst(pl_op.operand); |
| 1809 | const is_err_result = try self.isErr(error_union_ty, error_union); |
| 1810 | const reloc = try self.condBr(is_err_result); |
| 1811 | |
| 1812 | try self.genBody(body); |
| 1813 | |
| 1814 | try self.performReloc(reloc); |
| 1815 | break :result try self.errUnionPayload(error_union, error_union_ty); |
| 1816 | }; |
| 1817 | return self.finishAir(inst, result, .{ pl_op.operand, .none, .none }); |
| 1818 | } |
| 1819 | |
| 1799 | 1820 | fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1800 | 1821 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1801 | 1822 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| ... | ... | @@ -2475,6 +2496,30 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { |
| 2475 | 2496 | try table.ensureUnusedCapacity(self.gpa, additional_count); |
| 2476 | 2497 | } |
| 2477 | 2498 | |
| 2499 | /// Given an error union, returns the payload |
| 2500 | fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue { |
| 2501 | const err_ty = error_union_ty.errorUnionSet(); |
| 2502 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 2503 | if (err_ty.errorSetIsEmpty()) { |
| 2504 | return error_union_mcv; |
| 2505 | } |
| 2506 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 2507 | return MCValue.none; |
| 2508 | } |
| 2509 | |
| 2510 | const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*)); |
| 2511 | switch (error_union_mcv) { |
| 2512 | .register => return self.fail("TODO errUnionPayload for registers", .{}), |
| 2513 | .stack_offset => |off| { |
| 2514 | return MCValue{ .stack_offset = off - payload_offset }; |
| 2515 | }, |
| 2516 | .memory => |addr| { |
| 2517 | return MCValue{ .memory = addr + payload_offset }; |
| 2518 | }, |
| 2519 | else => unreachable, // invalid MCValue for an error union |
| 2520 | } |
| 2521 | } |
| 2522 | |
| 2478 | 2523 | fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError { |
| 2479 | 2524 | @setCold(true); |
| 2480 | 2525 | assert(self.err_msg == null); |