authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-04 19:54:00+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-05 10:37:08+02:00
logff00bbf4de0c6a91a1e98076ceb68d4cec127aee
treeb8f1c5edf4ad32c5c6da31fd29bd5e0d53e0b0b7
parent6da420419d79a735e88416056587c154b3cb3acd

x64: lower try and try_ptr


1 files changed, 68 insertions(+), 13 deletions(-)

src/arch/x86_64/CodeGen.zig+68-13
......@@ -681,8 +681,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
681681 .prefetch => try self.airPrefetch(inst),
682682 .mul_add => try self.airMulAdd(inst),
683683
684 .@"try" => @panic("TODO"),
685 .try_ptr => @panic("TODO"),
684 .@"try" => try self.airTry(inst),
685 .try_ptr => try self.airTryPtr(inst),
686686
687687 .dbg_var_ptr,
688688 .dbg_var_val,
......@@ -1807,14 +1807,24 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
18071807 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
18081808 }
18091809 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
1815fn genUnwrapErrorUnionPayloadMir(
1816 self: *Self,
1817 maybe_inst: ?Air.Inst.Index,
1818 err_union_ty: Type,
1819 err_union: MCValue,
1820) !MCValue {
18101821 const payload_ty = err_union_ty.errorUnionPayload();
18111822 const err_ty = err_union_ty.errorUnionSet();
1812 const operand = try self.resolveInst(ty_op.operand);
18131823
18141824 const result: MCValue = result: {
18151825 if (err_ty.errorSetCardinality() == .zero) {
18161826 // TODO check if we can reuse
1817 break :result operand;
1827 break :result err_union;
18181828 }
18191829
18201830 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
......@@ -1822,7 +1832,7 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
18221832 }
18231833
18241834 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);
1825 switch (operand) {
1835 switch (err_union) {
18261836 .stack_offset => |off| {
18271837 const offset = off - @intCast(i32, payload_off);
18281838 break :result MCValue{ .stack_offset = offset };
......@@ -1831,19 +1841,23 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
18311841 // TODO reuse operand
18321842 const lock = self.register_manager.lockRegAssumeUnused(reg);
18331843 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);
18351848 if (payload_off > 0) {
18361849 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 });
18381851 } else {
1839 try self.truncateRegister(payload_ty, result.register);
1852 try self.truncateRegister(payload_ty, result_reg);
18401853 }
1841 break :result result;
1854 break :result MCValue{ .register = result_reg };
18421855 },
1843 else => return self.fail("TODO implement unwrap_err_payload for {}", .{operand}),
1856 else => return self.fail("TODO implement genUnwrapErrorUnionPayloadMir for {}", .{err_union}),
18441857 }
18451858 };
1846 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1859
1860 return result;
18471861}
18481862
18491863// *(E!T) -> E
......@@ -4231,6 +4245,45 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
42314245 return self.finishAir(inst, result, .{ un_op, .none, .none });
42324246}
42334247
4248fn 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
4258fn 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
4268fn 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
42344287fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
42354288 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
42364289 const payload = try self.addExtra(Mir.DbgLineColumn{
......@@ -4596,7 +4649,7 @@ fn isNonNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCV
45964649 return MCValue{ .eflags = is_null_res.eflags.negate() };
45974650}
45984651
4599fn isErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {
4652fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {
46004653 const err_type = ty.errorUnionSet();
46014654
46024655 if (err_type.errorSetCardinality() == .zero) {
......@@ -4604,7 +4657,9 @@ fn isErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue
46044657 }
46054658
46064659 try self.spillEflagsIfOccupied();
4607 self.eflags_inst = inst;
4660 if (maybe_inst) |inst| {
4661 self.eflags_inst = inst;
4662 }
46084663
46094664 const err_off = errUnionErrorOffset(ty.errorUnionPayload(), self.target.*);
46104665 switch (operand) {