| ... | @@ -1530,21 +1530,23 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void | ... | @@ -1530,21 +1530,23 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void |
| 1530 | | 1530 | |
| 1531 | fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { | 1531 | fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 1532 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1532 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 1533 | const result = result: { |
| | 1534 | if (self.liveness.isUnused(inst)) break :result .dead; |
| 1533 | | 1535 | |
| 1534 | if (self.liveness.isUnused(inst)) { | 1536 | const tag = self.air.instructions.items(.tag)[inst]; |
| 1535 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); | 1537 | const ty = self.air.typeOfIndex(inst); |
| 1536 | } | | |
| 1537 | | | |
| 1538 | const tag = self.air.instructions.items(.tag)[inst]; | | |
| 1539 | const ty = self.air.typeOfIndex(inst); | | |
| 1540 | | 1538 | |
| 1541 | try self.spillRegisters(2, .{ .rax, .rdx }); | 1539 | if (ty.zigTypeTag() == .Float) { |
| | 1540 | break :result try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs); |
| | 1541 | } |
| 1542 | | 1542 | |
| 1543 | const lhs = try self.resolveInst(bin_op.lhs); | 1543 | try self.spillRegisters(2, .{ .rax, .rdx }); |
| 1544 | const rhs = try self.resolveInst(bin_op.rhs); | | |
| 1545 | | 1544 | |
| 1546 | const result = try self.genMulDivBinOp(tag, inst, ty, lhs, rhs); | 1545 | const lhs = try self.resolveInst(bin_op.lhs); |
| | 1546 | const rhs = try self.resolveInst(bin_op.rhs); |
| 1547 | | 1547 | |
| | 1548 | break :result try self.genMulDivBinOp(tag, inst, ty, lhs, rhs); |
| | 1549 | }; |
| 1548 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1550 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1549 | } | 1551 | } |
| 1550 | | 1552 | |
| ... | @@ -3288,10 +3290,10 @@ fn genMulDivBinOp( | ... | @@ -3288,10 +3290,10 @@ fn genMulDivBinOp( |
| 3288 | rhs: MCValue, | 3290 | rhs: MCValue, |
| 3289 | ) !MCValue { | 3291 | ) !MCValue { |
| 3290 | if (ty.zigTypeTag() == .Vector or ty.zigTypeTag() == .Float) { | 3292 | if (ty.zigTypeTag() == .Vector or ty.zigTypeTag() == .Float) { |
| 3291 | return self.fail("TODO implement genBinOp for {}", .{ty.fmtDebug()}); | 3293 | return self.fail("TODO implement genMulDivBinOp for {}", .{ty.fmtDebug()}); |
| 3292 | } | 3294 | } |
| 3293 | if (ty.abiSize(self.target.*) > 8) { | 3295 | if (ty.abiSize(self.target.*) > 8) { |
| 3294 | return self.fail("TODO implement genBinOp for {}", .{ty.fmtDebug()}); | 3296 | return self.fail("TODO implement genMulDivBinOp for {}", .{ty.fmtDebug()}); |
| 3295 | } | 3297 | } |
| 3296 | if (tag == .div_float) { | 3298 | if (tag == .div_float) { |
| 3297 | return self.fail("TODO implement genMulDivBinOp for div_float", .{}); | 3299 | return self.fail("TODO implement genMulDivBinOp for div_float", .{}); |
| ... | @@ -3516,11 +3518,31 @@ fn genBinOp( | ... | @@ -3516,11 +3518,31 @@ fn genBinOp( |
| 3516 | switch (tag) { | 3518 | switch (tag) { |
| 3517 | .add, | 3519 | .add, |
| 3518 | .addwrap, | 3520 | .addwrap, |
| 3519 | => try self.genBinOpMir(.add, lhs_ty, dst_mcv, src_mcv), | 3521 | => try self.genBinOpMir(switch (lhs_ty.tag()) { |
| | 3522 | else => .add, |
| | 3523 | .f32 => .addss, |
| | 3524 | .f64 => .addsd, |
| | 3525 | }, lhs_ty, dst_mcv, src_mcv), |
| 3520 | | 3526 | |
| 3521 | .sub, | 3527 | .sub, |
| 3522 | .subwrap, | 3528 | .subwrap, |
| 3523 | => try self.genBinOpMir(.sub, lhs_ty, dst_mcv, src_mcv), | 3529 | => try self.genBinOpMir(switch (lhs_ty.tag()) { |
| | 3530 | else => .sub, |
| | 3531 | .f32 => .subss, |
| | 3532 | .f64 => .subsd, |
| | 3533 | }, lhs_ty, dst_mcv, src_mcv), |
| | 3534 | |
| | 3535 | .mul => try self.genBinOpMir(switch (lhs_ty.tag()) { |
| | 3536 | .f32 => .mulss, |
| | 3537 | .f64 => .mulsd, |
| | 3538 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?) }), |
| | 3539 | }, lhs_ty, dst_mcv, src_mcv), |
| | 3540 | |
| | 3541 | .div_float => try self.genBinOpMir(switch (lhs_ty.tag()) { |
| | 3542 | .f32 => .divss, |
| | 3543 | .f64 => .divsd, |
| | 3544 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?) }), |
| | 3545 | }, lhs_ty, dst_mcv, src_mcv), |
| 3524 | | 3546 | |
| 3525 | .ptr_add, | 3547 | .ptr_add, |
| 3526 | .ptr_sub, | 3548 | .ptr_sub, |
| ... | @@ -3547,54 +3569,66 @@ fn genBinOp( | ... | @@ -3547,54 +3569,66 @@ fn genBinOp( |
| 3547 | | 3569 | |
| 3548 | .min, | 3570 | .min, |
| 3549 | .max, | 3571 | .max, |
| 3550 | => { | 3572 | => switch (lhs_ty.zigTypeTag()) { |
| 3551 | if (!lhs_ty.isAbiInt() or !rhs_ty.isAbiInt()) { | 3573 | .Int => { |
| 3552 | return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?) }); | 3574 | const mat_src_mcv = switch (src_mcv) { |
| 3553 | } | 3575 | .immediate => MCValue{ .register = try self.copyToTmpRegister(rhs_ty, src_mcv) }, |
| | 3576 | else => src_mcv, |
| | 3577 | }; |
| | 3578 | const mat_mcv_lock = switch (mat_src_mcv) { |
| | 3579 | .register => |reg| self.register_manager.lockReg(reg), |
| | 3580 | else => null, |
| | 3581 | }; |
| | 3582 | defer if (mat_mcv_lock) |lock| self.register_manager.unlockReg(lock); |
| 3554 | | 3583 | |
| 3555 | const mat_src_mcv = switch (src_mcv) { | 3584 | try self.genBinOpMir(.cmp, lhs_ty, dst_mcv, mat_src_mcv); |
| 3556 | .immediate => MCValue{ .register = try self.copyToTmpRegister(rhs_ty, src_mcv) }, | | |
| 3557 | else => src_mcv, | | |
| 3558 | }; | | |
| 3559 | const mat_mcv_lock = switch (mat_src_mcv) { | | |
| 3560 | .register => |reg| self.register_manager.lockReg(reg), | | |
| 3561 | else => null, | | |
| 3562 | }; | | |
| 3563 | defer if (mat_mcv_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 3564 | | 3585 | |
| 3565 | try self.genBinOpMir(.cmp, lhs_ty, dst_mcv, mat_src_mcv); | 3586 | const int_info = lhs_ty.intInfo(self.target.*); |
| | 3587 | const cc: Condition = switch (int_info.signedness) { |
| | 3588 | .unsigned => switch (tag) { |
| | 3589 | .min => .a, |
| | 3590 | .max => .b, |
| | 3591 | else => unreachable, |
| | 3592 | }, |
| | 3593 | .signed => switch (tag) { |
| | 3594 | .min => .g, |
| | 3595 | .max => .l, |
| | 3596 | else => unreachable, |
| | 3597 | }, |
| | 3598 | }; |
| 3566 | | 3599 | |
| 3567 | const int_info = lhs_ty.intInfo(self.target.*); | 3600 | const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*)); |
| 3568 | const cc: Condition = switch (int_info.signedness) { | 3601 | switch (dst_mcv) { |
| 3569 | .unsigned => switch (tag) { | 3602 | .register => |dst_reg| switch (mat_src_mcv) { |
| 3570 | .min => .a, | 3603 | .register => |src_reg| try self.asmCmovccRegisterRegister( |
| 3571 | .max => .b, | 3604 | registerAlias(dst_reg, abi_size), |
| | 3605 | registerAlias(src_reg, abi_size), |
| | 3606 | cc, |
| | 3607 | ), |
| | 3608 | .stack_offset => |off| try self.asmCmovccRegisterMemory( |
| | 3609 | registerAlias(dst_reg, abi_size), |
| | 3610 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }), |
| | 3611 | cc, |
| | 3612 | ), |
| | 3613 | else => unreachable, |
| | 3614 | }, |
| 3572 | else => unreachable, | 3615 | else => unreachable, |
| 3573 | }, | 3616 | } |
| 3574 | .signed => switch (tag) { | 3617 | }, |
| 3575 | .min => .g, | 3618 | .Float => try self.genBinOpMir(switch (lhs_ty.tag()) { |
| 3576 | .max => .l, | 3619 | .f32 => switch (tag) { |
| | 3620 | .min => .minss, |
| | 3621 | .max => .maxss, |
| 3577 | else => unreachable, | 3622 | else => unreachable, |
| 3578 | }, | 3623 | }, |
| 3579 | }; | 3624 | .f64 => switch (tag) { |
| 3580 | | 3625 | .min => .minsd, |
| 3581 | const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*)); | 3626 | .max => .maxsd, |
| 3582 | switch (dst_mcv) { | | |
| 3583 | .register => |dst_reg| switch (mat_src_mcv) { | | |
| 3584 | .register => |src_reg| try self.asmCmovccRegisterRegister( | | |
| 3585 | registerAlias(dst_reg, abi_size), | | |
| 3586 | registerAlias(src_reg, abi_size), | | |
| 3587 | cc, | | |
| 3588 | ), | | |
| 3589 | .stack_offset => |off| try self.asmCmovccRegisterMemory( | | |
| 3590 | registerAlias(dst_reg, abi_size), | | |
| 3591 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }), | | |
| 3592 | cc, | | |
| 3593 | ), | | |
| 3594 | else => unreachable, | 3627 | else => unreachable, |
| 3595 | }, | 3628 | }, |
| 3596 | else => unreachable, | 3629 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?) }), |
| 3597 | } | 3630 | }, lhs_ty, dst_mcv, src_mcv), |
| | 3631 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?) }), |
| 3598 | }, | 3632 | }, |
| 3599 | | 3633 | |
| 3600 | else => unreachable, | 3634 | else => unreachable, |
| ... | @@ -3626,29 +3660,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3626,29 +3660,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3626 | .register => |src_reg| switch (dst_ty.zigTypeTag()) { | 3660 | .register => |src_reg| switch (dst_ty.zigTypeTag()) { |
| 3627 | .Float => { | 3661 | .Float => { |
| 3628 | if (intrinsicsAllowed(self.target.*, dst_ty)) { | 3662 | if (intrinsicsAllowed(self.target.*, dst_ty)) { |
| 3629 | const actual_tag: Mir.Inst.Tag = switch (dst_ty.tag()) { | 3663 | return self.asmRegisterRegister(mir_tag, dst_reg.to128(), src_reg.to128()); |
| 3630 | .f32 => switch (mir_tag) { | | |
| 3631 | .add => .addss, | | |
| 3632 | .cmp => .ucomiss, | | |
| 3633 | else => return self.fail( | | |
| 3634 | "TODO genBinOpMir for f32 register-register with MIR tag {}", | | |
| 3635 | .{mir_tag}, | | |
| 3636 | ), | | |
| 3637 | }, | | |
| 3638 | .f64 => switch (mir_tag) { | | |
| 3639 | .add => .addsd, | | |
| 3640 | .cmp => .ucomisd, | | |
| 3641 | else => return self.fail( | | |
| 3642 | "TODO genBinOpMir for f64 register-register with MIR tag {}", | | |
| 3643 | .{mir_tag}, | | |
| 3644 | ), | | |
| 3645 | }, | | |
| 3646 | else => return self.fail( | | |
| 3647 | "TODO genBinOpMir for float register-register and type {}", | | |
| 3648 | .{dst_ty.fmtDebug()}, | | |
| 3649 | ), | | |
| 3650 | }; | | |
| 3651 | return self.asmRegisterRegister(actual_tag, dst_reg.to128(), src_reg.to128()); | | |
| 3652 | } | 3664 | } |
| 3653 | | 3665 | |
| 3654 | return self.fail("TODO genBinOpMir for float register-register and no intrinsics", .{}); | 3666 | return self.fail("TODO genBinOpMir for float register-register and no intrinsics", .{}); |
| ... | @@ -4307,7 +4319,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -4307,7 +4319,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 4307 | }; | 4319 | }; |
| 4308 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); | 4320 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 4309 | | 4321 | |
| 4310 | try self.genBinOpMir(.cmp, ty, dst_mcv, src_mcv); | 4322 | try self.genBinOpMir(switch (ty.tag()) { |
| | 4323 | else => .cmp, |
| | 4324 | .f32 => .ucomiss, |
| | 4325 | .f64 => .ucomisd, |
| | 4326 | }, ty, dst_mcv, src_mcv); |
| 4311 | | 4327 | |
| 4312 | break :result switch (signedness) { | 4328 | break :result switch (signedness) { |
| 4313 | .signed => MCValue{ .eflags = Condition.fromCompareOperatorSigned(op) }, | 4329 | .signed => MCValue{ .eflags = Condition.fromCompareOperatorSigned(op) }, |