diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2021-12-31 15:07:48 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2021-12-31 15:07:48 +0100 |
| commit | 5ec9f39dfe90890adef4dca1b48bf71176fe99f1 (patch) | |
| tree | 0735d4db200152217bf6d421ec2cfbc5939a09b9 | |
| parent | e7ac05e882fa4290af4a41e9cae63105bcacb283 (diff) | |
| download | zig-5ec9f39dfe90890adef4dca1b48bf71176fe99f1.tar.gz zig-5ec9f39dfe90890adef4dca1b48bf71176fe99f1.zip | |
stage2: implement isNull() and isNonNull()
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 59 |
1 files changed, 33 insertions, 26 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 86a5193c4d..32ca120dd1 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -2371,31 +2371,30 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none }); } -fn isNull(self: *Self, operand: MCValue) !MCValue { - _ = operand; - // Here you can specialize this instruction if it makes sense to, otherwise the default - // will call isNonNull and invert the result. - return self.fail("TODO call isNonNull and invert the result", .{}); +fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue { + try self.genBinMathOpMir(.cmp, ty, operand, MCValue{ .immediate = 0 }); + return MCValue{ .compare_flags_unsigned = .eq }; } -fn isNonNull(self: *Self, operand: MCValue) !MCValue { - _ = operand; - // Here you can specialize this instruction if it makes sense to, otherwise the default - // will call isNull and invert the result. - return self.fail("TODO call isNull and invert the result", .{}); +fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue { + const is_null_res = try self.isNull(ty, operand); + assert(is_null_res.compare_flags_unsigned == .eq); + return MCValue{ .compare_flags_unsigned = .neq }; } -fn isErr(self: *Self, operand: MCValue) !MCValue { +fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { + _ = ty; _ = operand; // Here you can specialize this instruction if it makes sense to, otherwise the default - // will call isNonNull and invert the result. + // will call isNonErr and invert the result. return self.fail("TODO call isNonErr and invert the result", .{}); } -fn isNonErr(self: *Self, operand: MCValue) !MCValue { +fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue { + _ = ty; _ = operand; // Here you can specialize this instruction if it makes sense to, otherwise the default - // will call isNull and invert the result. + // will call isErr and invert the result. return self.fail("TODO call isErr and invert the result", .{}); } @@ -2403,7 +2402,8 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void { const un_op = self.air.instructions.items(.data)[inst].un_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand = try self.resolveInst(un_op); - break :result try self.isNull(operand); + const ty = self.air.typeOf(un_op); + break :result try self.isNull(ty, operand); }; return self.finishAir(inst, result, .{ un_op, .none, .none }); } @@ -2420,8 +2420,9 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { break :blk try self.allocRegOrMem(inst, true); } }; - try self.load(operand, operand_ptr, self.air.typeOf(un_op)); - break :result try self.isNull(operand); + const ptr_ty = self.air.typeOf(un_op); + try self.load(operand, operand_ptr, ptr_ty); + break :result try self.isNull(ptr_ty.elemType(), operand); }; return self.finishAir(inst, result, .{ un_op, .none, .none }); } @@ -2430,7 +2431,8 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void { const un_op = self.air.instructions.items(.data)[inst].un_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand = try self.resolveInst(un_op); - break :result try self.isNonNull(operand); + const ty = self.air.typeOf(un_op); + break :result try self.isNonNull(ty, operand); }; return self.finishAir(inst, result, .{ un_op, .none, .none }); } @@ -2447,8 +2449,9 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void { break :blk try self.allocRegOrMem(inst, true); } }; - try self.load(operand, operand_ptr, self.air.typeOf(un_op)); - break :result try self.isNonNull(operand); + const ptr_ty = self.air.typeOf(un_op); + try self.load(operand, operand_ptr, ptr_ty); + break :result try self.isNonNull(ptr_ty.elemType(), operand); }; return self.finishAir(inst, result, .{ un_op, .none, .none }); } @@ -2457,7 +2460,8 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void { const un_op = self.air.instructions.items(.data)[inst].un_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand = try self.resolveInst(un_op); - break :result try self.isErr(operand); + const ty = self.air.typeOf(un_op); + break :result try self.isErr(ty, operand); }; return self.finishAir(inst, result, .{ un_op, .none, .none }); } @@ -2474,8 +2478,9 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void { break :blk try self.allocRegOrMem(inst, true); } }; - try self.load(operand, operand_ptr, self.air.typeOf(un_op)); - break :result try self.isErr(operand); + const ptr_ty = self.air.typeOf(un_op); + try self.load(operand, operand_ptr, ptr_ty); + break :result try self.isErr(ptr_ty.elemType(), operand); }; return self.finishAir(inst, result, .{ un_op, .none, .none }); } @@ -2484,7 +2489,8 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void { const un_op = self.air.instructions.items(.data)[inst].un_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand = try self.resolveInst(un_op); - break :result try self.isNonErr(operand); + const ty = self.air.typeOf(un_op); + break :result try self.isNonErr(ty, operand); }; return self.finishAir(inst, result, .{ un_op, .none, .none }); } @@ -2501,8 +2507,9 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void { break :blk try self.allocRegOrMem(inst, true); } }; - try self.load(operand, operand_ptr, self.air.typeOf(un_op)); - break :result try self.isNonErr(operand); + const ptr_ty = self.air.typeOf(un_op); + try self.load(operand, operand_ptr, ptr_ty); + break :result try self.isNonErr(ptr_ty.elemType(), operand); }; return self.finishAir(inst, result, .{ un_op, .none, .none }); } |
