| ... | @@ -677,8 +677,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -677,8 +677,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 677 | .prefetch => try self.airPrefetch(inst), | 677 | .prefetch => try self.airPrefetch(inst), |
| 678 | .mul_add => try self.airMulAdd(inst), | 678 | .mul_add => try self.airMulAdd(inst), |
| 679 | | 679 | |
| 680 | .@"try" => @panic("TODO"), | 680 | .@"try" => try self.airTry(inst), |
| 681 | .try_ptr => @panic("TODO"), | 681 | .try_ptr => try self.airTryPtr(inst), |
| 682 | | 682 | |
| 683 | .dbg_var_ptr, | 683 | .dbg_var_ptr, |
| 684 | .dbg_var_val, | 684 | .dbg_var_val, |
| ... | @@ -1837,8 +1837,8 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1837,8 +1837,8 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1837 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1837 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1838 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1838 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1839 | const error_union_ty = self.air.typeOf(ty_op.operand); | 1839 | const error_union_ty = self.air.typeOf(ty_op.operand); |
| 1840 | const mcv = try self.resolveInst(ty_op.operand); | 1840 | const error_union = try self.resolveInst(ty_op.operand); |
| 1841 | break :result try self.errUnionPayload(mcv, error_union_ty); | 1841 | break :result try self.errUnionPayload(error_union, error_union_ty); |
| 1842 | }; | 1842 | }; |
| 1843 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 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,6 +3705,42 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { |
| 3705 | return self.finishAir(inst, .dead, .{ operand, .none, .none }); | 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 | fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | 3744 | fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 3709 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 3745 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 3710 | const cond_inst = try self.resolveInst(pl_op.operand); | 3746 | const cond_inst = try self.resolveInst(pl_op.operand); |
| ... | @@ -3713,39 +3749,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3713,39 +3749,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 3713 | const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; | 3749 | const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; |
| 3714 | const liveness_condbr = self.liveness.getCondBr(inst); | 3750 | const liveness_condbr = self.liveness.getCondBr(inst); |
| 3715 | | 3751 | |
| 3716 | const reloc: Mir.Inst.Index = reloc: { | 3752 | const reloc: Mir.Inst.Index = try self.condBr(cond_inst); |
| 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 | }; | | |
| 3749 | | 3753 | |
| 3750 | // If the condition dies here in this condbr instruction, process | 3754 | // If the condition dies here in this condbr instruction, process |
| 3751 | // that death now instead of later as this has an effect on | 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,13 +4161,8 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void { |
| 4157 | .lhs = condition, | 4161 | .lhs = condition, |
| 4158 | .rhs = item, | 4162 | .rhs = item, |
| 4159 | } }; | 4163 | } }; |
| 4160 | const cmp_result = try self.cmp(operands, condition_ty, .neq); | 4164 | const cmp_result = try self.cmp(operands, condition_ty, .eq); |
| 4161 | | 4165 | relocs[0] = try self.condBr(cmp_result); |
| 4162 | relocs[0] = try self.addInst(.{ | | |
| 4163 | .tag = .b, | | |
| 4164 | .cond = cmp_result.cpsr_flags, | | |
| 4165 | .data = .{ .inst = undefined }, // populated later through performReloc | | |
| 4166 | }); | | |
| 4167 | } else { | 4166 | } else { |
| 4168 | return self.fail("TODO switch with multiple items", .{}); | 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,6 +5147,33 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 5148 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand }); | 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 | fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { | 5177 | fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { |
| 5152 | // First section of indexes correspond to a set number of constant values. | 5178 | // First section of indexes correspond to a set number of constant values. |
| 5153 | const ref_int = @enumToInt(inst); | 5179 | const ref_int = @enumToInt(inst); |