diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 87f6b9eb1026d63bb8f959f53a4eee4404b950ab..1e736a6e867be527eecb308e75ea55b2b6d3e3ca 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -3017,36 +3017,41 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { const rhs = try self.resolveInst(bin_op.rhs); const lhs_ty = self.air.typeOf(bin_op.lhs); - switch (lhs_ty.zigTypeTag()) { - .Optional => return self.fail("TODO ARM cmp optionals", .{}), + var int_buffer: Type.Payload.Bits = undefined; + const int_ty = switch (lhs_ty.zigTypeTag()) { + .Optional => blk: { + var opt_buffer: Type.Payload.ElemType = undefined; + const payload_ty = lhs_ty.optionalChild(&opt_buffer); + if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { + break :blk Type.initTag(.u1); + } else if (lhs_ty.isPtrLikeOptional()) { + break :blk Type.usize; + } else { + return self.fail("TODO ARM cmp non-pointer optionals", .{}); + } + }, .Float => return self.fail("TODO ARM cmp floats", .{}), - .Int, .Bool, .Pointer, .ErrorSet, .Enum => { - var int_buffer: Type.Payload.Bits = undefined; - const int_ty = switch (lhs_ty.zigTypeTag()) { - .Enum => lhs_ty.intTagType(&int_buffer), - .Int => lhs_ty, - .Bool => Type.initTag(.u1), - .Pointer => Type.usize, - .ErrorSet => Type.initTag(.u16), - else => unreachable, - }; - - const int_info = int_ty.intInfo(self.target.*); - if (int_info.bits <= 32) { - try self.spillCompareFlagsIfOccupied(); - self.compare_flags_inst = inst; - - _ = try self.binOp(.cmp_eq, inst, lhs, rhs, int_ty, int_ty); - - break :result switch (int_info.signedness) { - .signed => MCValue{ .compare_flags_signed = op }, - .unsigned => MCValue{ .compare_flags_unsigned = op }, - }; - } else { - return self.fail("TODO ARM cmp for ints > 32 bits", .{}); - } - }, + .Enum => lhs_ty.intTagType(&int_buffer), + .Int => lhs_ty, + .Bool => Type.initTag(.u1), + .Pointer => Type.usize, + .ErrorSet => Type.initTag(.u16), else => unreachable, + }; + + const int_info = int_ty.intInfo(self.target.*); + if (int_info.bits <= 32) { + try self.spillCompareFlagsIfOccupied(); + self.compare_flags_inst = inst; + + _ = try self.binOp(.cmp_eq, inst, lhs, rhs, int_ty, int_ty); + + break :result switch (int_info.signedness) { + .signed => MCValue{ .compare_flags_signed = op }, + .unsigned => MCValue{ .compare_flags_unsigned = op }, + }; + } else { + return self.fail("TODO ARM cmp for ints > 32 bits", .{}); } }; return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); diff --git a/test/behavior/optional.zig b/test/behavior/optional.zig index d9c16da06612ad800e2fc73b8bbdbebe2220331d..10d829a2c0982c1fd29352058cc515206cd46bec 100644 --- a/test/behavior/optional.zig +++ b/test/behavior/optional.zig @@ -33,8 +33,6 @@ test "optional pointer to size zero struct" { } test "equality compare optional pointers" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - try testNullPtrsEql(); comptime try testNullPtrsEql(); }