| ... | ... | @@ -677,8 +677,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 677 | 677 | .prefetch => try self.airPrefetch(inst), |
| 678 | 678 | .mul_add => try self.airMulAdd(inst), |
| 679 | 679 | |
| 680 | | .@"try" => @panic("TODO"), |
| 681 | | .try_ptr => @panic("TODO"), |
| 680 | .@"try" => try self.airTry(inst), |
| 681 | .try_ptr => try self.airTryPtr(inst), |
| 682 | 682 | |
| 683 | 683 | .dbg_var_ptr, |
| 684 | 684 | .dbg_var_val, |
| ... | ... | @@ -1837,8 +1837,8 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1837 | 1837 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1838 | 1838 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1839 | 1839 | 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); |
| 1842 | 1842 | }; |
| 1843 | 1843 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1844 | 1844 | } |
| ... | ... | @@ -3705,6 +3705,42 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { |
| 3705 | 3705 | return self.finishAir(inst, .dead, .{ operand, .none, .none }); |
| 3706 | 3706 | } |
| 3707 | 3707 | |
| 3708 | /// Given a boolean condition, emit a jump that is taken when that |
| 3709 | /// condition is false. |
| 3710 | fn 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 | |
| 3708 | 3744 | fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 3709 | 3745 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 3710 | 3746 | const cond_inst = try self.resolveInst(pl_op.operand); |
| ... | ... | @@ -3713,39 +3749,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 3713 | 3749 | const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; |
| 3714 | 3750 | const liveness_condbr = self.liveness.getCondBr(inst); |
| 3715 | 3751 | |
| 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); |
| 3749 | 3753 | |
| 3750 | 3754 | // If the condition dies here in this condbr instruction, process |
| 3751 | 3755 | // 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 { |
| 4157 | 4161 | .lhs = condition, |
| 4158 | 4162 | .rhs = item, |
| 4159 | 4163 | } }; |
| 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); |
| 4167 | 4166 | } else { |
| 4168 | 4167 | return self.fail("TODO switch with multiple items", .{}); |
| 4169 | 4168 | } |
| ... | ... | @@ -5148,6 +5147,33 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 5148 | 5147 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand }); |
| 5149 | 5148 | } |
| 5150 | 5149 | |
| 5150 | fn 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 | |
| 5168 | fn 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 | |
| 5151 | 5177 | fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { |
| 5152 | 5178 | // First section of indexes correspond to a set number of constant values. |
| 5153 | 5179 | const ref_int = @enumToInt(inst); |