authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-06-06 12:34:19+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-06-06 14:22:40+02:00
loga34f3ff04a9a6d1c3bf7b818a8de28c453cc53d6
tree970a58ccddac96a2e23718eb5467c588556203b2
parentff00bbf4de0c6a91a1e98076ceb68d4cec127aee
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: implement `try` AIR instruction


1 files changed, 70 insertions(+), 44 deletions(-)

src/arch/arm/CodeGen.zig+70-44
......@@ -677,8 +677,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
677677 .prefetch => try self.airPrefetch(inst),
678678 .mul_add => try self.airMulAdd(inst),
679679
680 .@"try" => @panic("TODO"),
681 .try_ptr => @panic("TODO"),
680 .@"try" => try self.airTry(inst),
681 .try_ptr => try self.airTryPtr(inst),
682682
683683 .dbg_var_ptr,
684684 .dbg_var_val,
......@@ -1837,8 +1837,8 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
18371837 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
18381838 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
18391839 const error_union_ty = self.air.typeOf(ty_op.operand);
1840 const mcv = try self.resolveInst(ty_op.operand);
1841 break :result try self.errUnionPayload(mcv, error_union_ty);
1840 const error_union = try self.resolveInst(ty_op.operand);
1841 break :result try self.errUnionPayload(error_union, error_union_ty);
18421842 };
18431843 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
18441844}
......@@ -3705,6 +3705,42 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
37053705 return self.finishAir(inst, .dead, .{ operand, .none, .none });
37063706}
37073707
3708/// Given a boolean condition, emit a jump that is taken when that
3709/// condition is false.
3710fn condBr(self: *Self, condition: MCValue) !Mir.Inst.Index {
3711 const condition_code: Condition = switch (condition) {
3712 .cpsr_flags => |cond| cond.negate(),
3713 else => blk: {
3714 const reg = switch (condition) {
3715 .register => |r| r,
3716 else => try self.copyToTmpRegister(Type.bool, condition),
3717 };
3718
3719 try self.spillCompareFlagsIfOccupied();
3720
3721 // cmp reg, 1
3722 // bne ...
3723 _ = try self.addInst(.{
3724 .tag = .cmp,
3725 .cond = .al,
3726 .data = .{ .rr_op = .{
3727 .rd = .r0,
3728 .rn = reg,
3729 .op = Instruction.Operand.imm(1, 0),
3730 } },
3731 });
3732
3733 break :blk .ne;
3734 },
3735 };
3736
3737 return try self.addInst(.{
3738 .tag = .b,
3739 .cond = condition_code,
3740 .data = .{ .inst = undefined }, // populated later through performReloc
3741 });
3742}
3743
37083744fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
37093745 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
37103746 const cond_inst = try self.resolveInst(pl_op.operand);
......@@ -3713,39 +3749,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
37133749 const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
37143750 const liveness_condbr = self.liveness.getCondBr(inst);
37153751
3716 const reloc: Mir.Inst.Index = reloc: {
3717 const condition: Condition = switch (cond_inst) {
3718 .cpsr_flags => |cond| cond.negate(),
3719 else => blk: {
3720 const reg = switch (cond_inst) {
3721 .register => |r| r,
3722 else => try self.copyToTmpRegister(Type.bool, cond_inst),
3723 };
3724
3725 try self.spillCompareFlagsIfOccupied();
3726
3727 // cmp reg, 1
3728 // bne ...
3729 _ = try self.addInst(.{
3730 .tag = .cmp,
3731 .cond = .al,
3732 .data = .{ .rr_op = .{
3733 .rd = .r0,
3734 .rn = reg,
3735 .op = Instruction.Operand.imm(1, 0),
3736 } },
3737 });
3738
3739 break :blk .ne;
3740 },
3741 };
3742
3743 break :reloc try self.addInst(.{
3744 .tag = .b,
3745 .cond = condition,
3746 .data = .{ .inst = undefined }, // populated later through performReloc
3747 });
3748 };
3752 const reloc: Mir.Inst.Index = try self.condBr(cond_inst);
37493753
37503754 // If the condition dies here in this condbr instruction, process
37513755 // that death now instead of later as this has an effect on
......@@ -4157,13 +4161,8 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
41574161 .lhs = condition,
41584162 .rhs = item,
41594163 } };
4160 const cmp_result = try self.cmp(operands, condition_ty, .neq);
4161
4162 relocs[0] = try self.addInst(.{
4163 .tag = .b,
4164 .cond = cmp_result.cpsr_flags,
4165 .data = .{ .inst = undefined }, // populated later through performReloc
4166 });
4164 const cmp_result = try self.cmp(operands, condition_ty, .eq);
4165 relocs[0] = try self.condBr(cmp_result);
41674166 } else {
41684167 return self.fail("TODO switch with multiple items", .{});
41694168 }
......@@ -5148,6 +5147,33 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
51485147 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand });
51495148}
51505149
5150fn airTry(self: *Self, inst: Air.Inst.Index) !void {
5151 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
5152 const extra = self.air.extraData(Air.Try, pl_op.payload);
5153 const body = self.air.extra[extra.end..][0..extra.data.body_len];
5154 const result: MCValue = result: {
5155 const error_union_ty = self.air.typeOf(pl_op.operand);
5156 const error_union = try self.resolveInst(pl_op.operand);
5157 const is_err_result = try self.isErr(error_union_ty, error_union);
5158 const reloc = try self.condBr(is_err_result);
5159
5160 try self.genBody(body);
5161
5162 try self.performReloc(reloc);
5163 break :result try self.errUnionPayload(error_union, error_union_ty);
5164 };
5165 return self.finishAir(inst, result, .{ pl_op.operand, .none, .none });
5166}
5167
5168fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void {
5169 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5170 const extra = self.air.extraData(Air.TryPtr, ty_pl.payload);
5171 const body = self.air.extra[extra.end..][0..extra.data.body_len];
5172 _ = body;
5173 return self.fail("TODO implement airTryPtr for arm", .{});
5174 // return self.finishAir(inst, result, .{ extra.data.ptr, .none, .none });
5175}
5176
51515177fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
51525178 // First section of indexes correspond to a set number of constant values.
51535179 const ref_int = @enumToInt(inst);