| ... | @@ -586,9 +586,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -586,9 +586,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 586 | .intcast => try self.airIntCast(inst), | 586 | .intcast => try self.airIntCast(inst), |
| 587 | .trunc => @panic("TODO try self.airTrunc(inst)"), | 587 | .trunc => @panic("TODO try self.airTrunc(inst)"), |
| 588 | .bool_to_int => @panic("TODO try self.airBoolToInt(inst)"), | 588 | .bool_to_int => @panic("TODO try self.airBoolToInt(inst)"), |
| 589 | .is_non_null => @panic("TODO try self.airIsNonNull(inst)"), | 589 | .is_non_null => try self.airIsNonNull(inst), |
| 590 | .is_non_null_ptr => @panic("TODO try self.airIsNonNullPtr(inst)"), | 590 | .is_non_null_ptr => @panic("TODO try self.airIsNonNullPtr(inst)"), |
| 591 | .is_null => @panic("TODO try self.airIsNull(inst)"), | 591 | .is_null => try self.airIsNull(inst), |
| 592 | .is_null_ptr => @panic("TODO try self.airIsNullPtr(inst)"), | 592 | .is_null_ptr => @panic("TODO try self.airIsNullPtr(inst)"), |
| 593 | .is_non_err => try self.airIsNonErr(inst), | 593 | .is_non_err => try self.airIsNonErr(inst), |
| 594 | .is_non_err_ptr => @panic("TODO try self.airIsNonErrPtr(inst)"), | 594 | .is_non_err_ptr => @panic("TODO try self.airIsNonErrPtr(inst)"), |
| ... | @@ -1503,6 +1503,24 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1503,6 +1503,24 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1503 | return self.finishAir(inst, result, .{ un_op, .none, .none }); | 1503 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 1504 | } | 1504 | } |
| 1505 | | 1505 | |
| | 1506 | fn airIsNull(self: *Self, inst: Air.Inst.Index) !void { |
| | 1507 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| | 1508 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| | 1509 | const operand = try self.resolveInst(un_op); |
| | 1510 | break :result try self.isNull(operand); |
| | 1511 | }; |
| | 1512 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| | 1513 | } |
| | 1514 | |
| | 1515 | fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void { |
| | 1516 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| | 1517 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| | 1518 | const operand = try self.resolveInst(un_op); |
| | 1519 | break :result try self.isNonNull(operand); |
| | 1520 | }; |
| | 1521 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| | 1522 | } |
| | 1523 | |
| 1506 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | 1524 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 1507 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1525 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1508 | const elem_ty = self.air.typeOfIndex(inst); | 1526 | const elem_ty = self.air.typeOfIndex(inst); |
| ... | @@ -3290,6 +3308,28 @@ fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue { | ... | @@ -3290,6 +3308,28 @@ fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 3290 | } | 3308 | } |
| 3291 | } | 3309 | } |
| 3292 | | 3310 | |
| | 3311 | fn isNull(self: *Self, operand: MCValue) !MCValue { |
| | 3312 | _ = operand; |
| | 3313 | // Here you can specialize this instruction if it makes sense to, otherwise the default |
| | 3314 | // will call isNonNull and invert the result. |
| | 3315 | return self.fail("TODO call isNonNull and invert the result", .{}); |
| | 3316 | } |
| | 3317 | |
| | 3318 | fn isNonNull(self: *Self, operand: MCValue) !MCValue { |
| | 3319 | // Call isNull, then negate the result. |
| | 3320 | const is_null_result = try self.isNull(operand); |
| | 3321 | switch (is_null_result) { |
| | 3322 | .condition_flags => |op| { |
| | 3323 | return MCValue{ .condition_flags = .{ .cond = op.cond.negate(), .ccr = op.ccr } }; |
| | 3324 | }, |
| | 3325 | .immediate => |imm| { |
| | 3326 | assert(imm == 0); |
| | 3327 | return MCValue{ .immediate = 1 }; |
| | 3328 | }, |
| | 3329 | else => unreachable, |
| | 3330 | } |
| | 3331 | } |
| | 3332 | |
| 3293 | fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigTomb { | 3333 | fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigTomb { |
| 3294 | try self.ensureProcessDeathCapacity(operand_count + 1); | 3334 | try self.ensureProcessDeathCapacity(operand_count + 1); |
| 3295 | return BigTomb{ | 3335 | return BigTomb{ |