authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-31 15:07:48+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-31 15:07:48+01:00
log5ec9f39dfe90890adef4dca1b48bf71176fe99f1
tree0735d4db200152217bf6d421ec2cfbc5939a09b9
parente7ac05e882fa4290af4a41e9cae63105bcacb283

stage2: implement isNull() and isNonNull()


1 files changed, 33 insertions(+), 26 deletions(-)

src/arch/x86_64/CodeGen.zig+33-26
...@@ -2371,31 +2371,30 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2371,31 +2371,30 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
2371 return self.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none });2371 return self.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none });
2372}2372}
23732373
2374fn isNull(self: *Self, operand: MCValue) !MCValue {2374fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue {
2375 _ = operand;2375 try self.genBinMathOpMir(.cmp, ty, operand, MCValue{ .immediate = 0 });
2376 // Here you can specialize this instruction if it makes sense to, otherwise the default2376 return MCValue{ .compare_flags_unsigned = .eq };
2377 // will call isNonNull and invert the result.
2378 return self.fail("TODO call isNonNull and invert the result", .{});
2379}2377}
23802378
2381fn isNonNull(self: *Self, operand: MCValue) !MCValue {2379fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue {
2382 _ = operand;2380 const is_null_res = try self.isNull(ty, operand);
2383 // Here you can specialize this instruction if it makes sense to, otherwise the default2381 assert(is_null_res.compare_flags_unsigned == .eq);
2384 // will call isNull and invert the result.2382 return MCValue{ .compare_flags_unsigned = .neq };
2385 return self.fail("TODO call isNull and invert the result", .{});
2386}2383}
23872384
2388fn isErr(self: *Self, operand: MCValue) !MCValue {2385fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
2386 _ = ty;
2389 _ = operand;2387 _ = operand;
2390 // Here you can specialize this instruction if it makes sense to, otherwise the default2388 // Here you can specialize this instruction if it makes sense to, otherwise the default
2391 // will call isNonNull and invert the result.2389 // will call isNonErr and invert the result.
2392 return self.fail("TODO call isNonErr and invert the result", .{});2390 return self.fail("TODO call isNonErr and invert the result", .{});
2393}2391}
23942392
2395fn isNonErr(self: *Self, operand: MCValue) !MCValue {2393fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
2394 _ = ty;
2396 _ = operand;2395 _ = operand;
2397 // Here you can specialize this instruction if it makes sense to, otherwise the default2396 // Here you can specialize this instruction if it makes sense to, otherwise the default
2398 // will call isNull and invert the result.2397 // will call isErr and invert the result.
2399 return self.fail("TODO call isErr and invert the result", .{});2398 return self.fail("TODO call isErr and invert the result", .{});
2400}2399}
24012400
...@@ -2403,7 +2402,8 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -2403,7 +2402,8 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
2403 const un_op = self.air.instructions.items(.data)[inst].un_op;2402 const un_op = self.air.instructions.items(.data)[inst].un_op;
2404 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2403 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2405 const operand = try self.resolveInst(un_op);2404 const operand = try self.resolveInst(un_op);
2406 break :result try self.isNull(operand);2405 const ty = self.air.typeOf(un_op);
2406 break :result try self.isNull(ty, operand);
2407 };2407 };
2408 return self.finishAir(inst, result, .{ un_op, .none, .none });2408 return self.finishAir(inst, result, .{ un_op, .none, .none });
2409}2409}
...@@ -2420,8 +2420,9 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2420,8 +2420,9 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
2420 break :blk try self.allocRegOrMem(inst, true);2420 break :blk try self.allocRegOrMem(inst, true);
2421 }2421 }
2422 };2422 };
2423 try self.load(operand, operand_ptr, self.air.typeOf(un_op));2423 const ptr_ty = self.air.typeOf(un_op);
2424 break :result try self.isNull(operand);2424 try self.load(operand, operand_ptr, ptr_ty);
2425 break :result try self.isNull(ptr_ty.elemType(), operand);
2425 };2426 };
2426 return self.finishAir(inst, result, .{ un_op, .none, .none });2427 return self.finishAir(inst, result, .{ un_op, .none, .none });
2427}2428}
...@@ -2430,7 +2431,8 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -2430,7 +2431,8 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
2430 const un_op = self.air.instructions.items(.data)[inst].un_op;2431 const un_op = self.air.instructions.items(.data)[inst].un_op;
2431 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2432 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2432 const operand = try self.resolveInst(un_op);2433 const operand = try self.resolveInst(un_op);
2433 break :result try self.isNonNull(operand);2434 const ty = self.air.typeOf(un_op);
2435 break :result try self.isNonNull(ty, operand);
2434 };2436 };
2435 return self.finishAir(inst, result, .{ un_op, .none, .none });2437 return self.finishAir(inst, result, .{ un_op, .none, .none });
2436}2438}
...@@ -2447,8 +2449,9 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2447,8 +2449,9 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
2447 break :blk try self.allocRegOrMem(inst, true);2449 break :blk try self.allocRegOrMem(inst, true);
2448 }2450 }
2449 };2451 };
2450 try self.load(operand, operand_ptr, self.air.typeOf(un_op));2452 const ptr_ty = self.air.typeOf(un_op);
2451 break :result try self.isNonNull(operand);2453 try self.load(operand, operand_ptr, ptr_ty);
2454 break :result try self.isNonNull(ptr_ty.elemType(), operand);
2452 };2455 };
2453 return self.finishAir(inst, result, .{ un_op, .none, .none });2456 return self.finishAir(inst, result, .{ un_op, .none, .none });
2454}2457}
...@@ -2457,7 +2460,8 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2457,7 +2460,8 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
2457 const un_op = self.air.instructions.items(.data)[inst].un_op;2460 const un_op = self.air.instructions.items(.data)[inst].un_op;
2458 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2461 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2459 const operand = try self.resolveInst(un_op);2462 const operand = try self.resolveInst(un_op);
2460 break :result try self.isErr(operand);2463 const ty = self.air.typeOf(un_op);
2464 break :result try self.isErr(ty, operand);
2461 };2465 };
2462 return self.finishAir(inst, result, .{ un_op, .none, .none });2466 return self.finishAir(inst, result, .{ un_op, .none, .none });
2463}2467}
...@@ -2474,8 +2478,9 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2474,8 +2478,9 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
2474 break :blk try self.allocRegOrMem(inst, true);2478 break :blk try self.allocRegOrMem(inst, true);
2475 }2479 }
2476 };2480 };
2477 try self.load(operand, operand_ptr, self.air.typeOf(un_op));2481 const ptr_ty = self.air.typeOf(un_op);
2478 break :result try self.isErr(operand);2482 try self.load(operand, operand_ptr, ptr_ty);
2483 break :result try self.isErr(ptr_ty.elemType(), operand);
2479 };2484 };
2480 return self.finishAir(inst, result, .{ un_op, .none, .none });2485 return self.finishAir(inst, result, .{ un_op, .none, .none });
2481}2486}
...@@ -2484,7 +2489,8 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2484,7 +2489,8 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
2484 const un_op = self.air.instructions.items(.data)[inst].un_op;2489 const un_op = self.air.instructions.items(.data)[inst].un_op;
2485 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2490 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2486 const operand = try self.resolveInst(un_op);2491 const operand = try self.resolveInst(un_op);
2487 break :result try self.isNonErr(operand);2492 const ty = self.air.typeOf(un_op);
2493 break :result try self.isNonErr(ty, operand);
2488 };2494 };
2489 return self.finishAir(inst, result, .{ un_op, .none, .none });2495 return self.finishAir(inst, result, .{ un_op, .none, .none });
2490}2496}
...@@ -2501,8 +2507,9 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2501,8 +2507,9 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
2501 break :blk try self.allocRegOrMem(inst, true);2507 break :blk try self.allocRegOrMem(inst, true);
2502 }2508 }
2503 };2509 };
2504 try self.load(operand, operand_ptr, self.air.typeOf(un_op));2510 const ptr_ty = self.air.typeOf(un_op);
2505 break :result try self.isNonErr(operand);2511 try self.load(operand, operand_ptr, ptr_ty);
2512 break :result try self.isNonErr(ptr_ty.elemType(), operand);
2506 };2513 };
2507 return self.finishAir(inst, result, .{ un_op, .none, .none });2514 return self.finishAir(inst, result, .{ un_op, .none, .none });
2508}2515}