| ... | @@ -1628,7 +1628,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1628,7 +1628,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 1628 | const reg_bits = self.regBitSize(ty); | 1628 | const reg_bits = self.regBitSize(ty); |
| 1629 | const cc: Condition = if (ty.isSignedInt()) cc: { | 1629 | const cc: Condition = if (ty.isSignedInt()) cc: { |
| 1630 | try self.genSetReg(ty, limit_reg, dst_mcv); | 1630 | try self.genSetReg(ty, limit_reg, dst_mcv); |
| 1631 | try self.genBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); | 1631 | try self.genShiftBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| 1632 | try self.genBinOpMir(.xor, ty, limit_mcv, .{ | 1632 | try self.genBinOpMir(.xor, ty, limit_mcv, .{ |
| 1633 | .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1, | 1633 | .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1, |
| 1634 | }); | 1634 | }); |
| ... | @@ -1681,7 +1681,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1681,7 +1681,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 1681 | const reg_bits = self.regBitSize(ty); | 1681 | const reg_bits = self.regBitSize(ty); |
| 1682 | const cc: Condition = if (ty.isSignedInt()) cc: { | 1682 | const cc: Condition = if (ty.isSignedInt()) cc: { |
| 1683 | try self.genSetReg(ty, limit_reg, dst_mcv); | 1683 | try self.genSetReg(ty, limit_reg, dst_mcv); |
| 1684 | try self.genBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); | 1684 | try self.genShiftBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| 1685 | try self.genBinOpMir(.xor, ty, limit_mcv, .{ | 1685 | try self.genBinOpMir(.xor, ty, limit_mcv, .{ |
| 1686 | .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1, | 1686 | .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1, |
| 1687 | }); | 1687 | }); |
| ... | @@ -1735,7 +1735,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1735,7 +1735,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 1735 | const cc: Condition = if (ty.isSignedInt()) cc: { | 1735 | const cc: Condition = if (ty.isSignedInt()) cc: { |
| 1736 | try self.genSetReg(ty, limit_reg, lhs_mcv); | 1736 | try self.genSetReg(ty, limit_reg, lhs_mcv); |
| 1737 | try self.genBinOpMir(.xor, ty, limit_mcv, rhs_mcv); | 1737 | try self.genBinOpMir(.xor, ty, limit_mcv, rhs_mcv); |
| 1738 | try self.genBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); | 1738 | try self.genShiftBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| 1739 | try self.genBinOpMir(.xor, ty, limit_mcv, .{ | 1739 | try self.genBinOpMir(.xor, ty, limit_mcv, .{ |
| 1740 | .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1, | 1740 | .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1, |
| 1741 | }); | 1741 | }); |
| ... | @@ -2509,16 +2509,13 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2509,16 +2509,13 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 2509 | | 2509 | |
| 2510 | fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { | 2510 | fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 2511 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2511 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2512 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 2512 | const result = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2513 | const operand = try self.resolveInst(ty_op.operand); | 2513 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 2514 | const dst_mcv: MCValue = blk: { | 2514 | if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv; |
| 2515 | switch (operand) { | 2515 | |
| 2516 | .stack_offset => |off| { | 2516 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 2517 | break :blk MCValue{ .stack_offset = off }; | 2517 | const dst_ty = self.air.typeOfIndex(inst); |
| 2518 | }, | 2518 | try self.setRegOrMem(dst_ty, dst_mcv, src_mcv); |
| 2519 | else => return self.fail("TODO implement slice_ptr for {}", .{operand}), | | |
| 2520 | } | | |
| 2521 | }; | | |
| 2522 | break :result dst_mcv; | 2519 | break :result dst_mcv; |
| 2523 | }; | 2520 | }; |
| 2524 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 2521 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| ... | @@ -4402,7 +4399,7 @@ fn genBinOp( | ... | @@ -4402,7 +4399,7 @@ fn genBinOp( |
| 4402 | else => {}, | 4399 | else => {}, |
| 4403 | } | 4400 | } |
| 4404 | | 4401 | |
| 4405 | const is_commutative: bool = switch (tag) { | 4402 | const is_commutative = switch (tag) { |
| 4406 | .add, | 4403 | .add, |
| 4407 | .addwrap, | 4404 | .addwrap, |
| 4408 | .bool_or, | 4405 | .bool_or, |
| ... | @@ -4416,6 +4413,20 @@ fn genBinOp( | ... | @@ -4416,6 +4413,20 @@ fn genBinOp( |
| 4416 | | 4413 | |
| 4417 | else => false, | 4414 | else => false, |
| 4418 | }; | 4415 | }; |
| | 4416 | const needs_reg_dst = switch (tag) { |
| | 4417 | .add, |
| | 4418 | .addwrap, |
| | 4419 | .sub, |
| | 4420 | .subwrap, |
| | 4421 | .mul, |
| | 4422 | .div_float, |
| | 4423 | .div_exact, |
| | 4424 | .div_trunc, |
| | 4425 | .div_floor, |
| | 4426 | => lhs_ty.isRuntimeFloat(), |
| | 4427 | |
| | 4428 | else => false, |
| | 4429 | }; |
| 4419 | | 4430 | |
| 4420 | const lhs_lock: ?RegisterLock = switch (lhs) { | 4431 | const lhs_lock: ?RegisterLock = switch (lhs) { |
| 4421 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), | 4432 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), |
| ... | @@ -4432,10 +4443,10 @@ fn genBinOp( | ... | @@ -4432,10 +4443,10 @@ fn genBinOp( |
| 4432 | var flipped: bool = false; | 4443 | var flipped: bool = false; |
| 4433 | const dst_mcv: MCValue = blk: { | 4444 | const dst_mcv: MCValue = blk: { |
| 4434 | if (maybe_inst) |inst| { | 4445 | if (maybe_inst) |inst| { |
| 4435 | if (lhs.isRegister() and self.reuseOperand(inst, lhs_air, 0, lhs)) { | 4446 | if ((!needs_reg_dst or lhs.isRegister()) and self.reuseOperand(inst, lhs_air, 0, lhs)) { |
| 4436 | break :blk lhs; | 4447 | break :blk lhs; |
| 4437 | } | 4448 | } |
| 4438 | if (is_commutative and rhs.isRegister() and self.reuseOperand(inst, rhs_air, 1, rhs)) { | 4449 | if (is_commutative and (!needs_reg_dst or rhs.isRegister()) and self.reuseOperand(inst, rhs_air, 1, rhs)) { |
| 4439 | flipped = true; | 4450 | flipped = true; |
| 4440 | break :blk rhs; | 4451 | break :blk rhs; |
| 4441 | } | 4452 | } |
| ... | @@ -4485,33 +4496,37 @@ fn genBinOp( | ... | @@ -4485,33 +4496,37 @@ fn genBinOp( |
| 4485 | | 4496 | |
| 4486 | .div_float, | 4497 | .div_float, |
| 4487 | .div_exact, | 4498 | .div_exact, |
| 4488 | => try self.genBinOpMir(switch (lhs_ty.tag()) { | | |
| 4489 | .f32 => .divss, | | |
| 4490 | .f64 => .divsd, | | |
| 4491 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?) }), | | |
| 4492 | }, lhs_ty, dst_mcv, src_mcv), | | |
| 4493 | | | |
| 4494 | .div_trunc, | 4499 | .div_trunc, |
| 4495 | .div_floor, | 4500 | .div_floor, |
| 4496 | => { | 4501 | => { |
| 4497 | try self.genBinOpMir(switch (lhs_ty.tag()) { | 4502 | try self.genBinOpMir(switch (lhs_ty.tag()) { |
| 4498 | .f32 => .divss, | 4503 | .f32 => .divss, |
| 4499 | .f64 => .divsd, | 4504 | .f64 => .divsd, |
| 4500 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?) }), | 4505 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ |
| | 4506 | @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| | 4507 | }), |
| 4501 | }, lhs_ty, dst_mcv, src_mcv); | 4508 | }, lhs_ty, dst_mcv, src_mcv); |
| 4502 | if (Target.x86.featureSetHas(self.target.cpu.features, .sse4_1)) { | 4509 | switch (tag) { |
| 4503 | const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*)); | 4510 | .div_float, |
| 4504 | const dst_alias = registerAlias(dst_mcv.register, abi_size); | 4511 | .div_exact, |
| 4505 | try self.asmRegisterRegisterImmediate(switch (lhs_ty.tag()) { | 4512 | => {}, |
| 4506 | .f32 => .roundss, | 4513 | .div_trunc, |
| 4507 | .f64 => .roundsd, | 4514 | .div_floor, |
| 4508 | else => unreachable, | 4515 | => if (Target.x86.featureSetHas(self.target.cpu.features, .sse4_1)) { |
| 4509 | }, dst_alias, dst_alias, Immediate.u(switch (tag) { | 4516 | const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*)); |
| 4510 | .div_trunc => 0b1_0_11, | 4517 | const dst_alias = registerAlias(dst_mcv.register, abi_size); |
| 4511 | .div_floor => 0b1_0_01, | 4518 | try self.asmRegisterRegisterImmediate(switch (lhs_ty.tag()) { |
| 4512 | else => unreachable, | 4519 | .f32 => .roundss, |
| 4513 | })); | 4520 | .f64 => .roundsd, |
| 4514 | } else return self.fail("TODO implement round without sse4_1", .{}); | 4521 | else => unreachable, |
| | 4522 | }, dst_alias, dst_alias, Immediate.u(switch (tag) { |
| | 4523 | .div_trunc => 0b1_0_11, |
| | 4524 | .div_floor => 0b1_0_01, |
| | 4525 | else => unreachable, |
| | 4526 | })); |
| | 4527 | } else return self.fail("TODO implement round without sse4_1", .{}), |
| | 4528 | else => unreachable, |
| | 4529 | } |
| 4515 | }, | 4530 | }, |
| 4516 | | 4531 | |
| 4517 | .ptr_add, | 4532 | .ptr_add, |
| ... | @@ -4568,7 +4583,13 @@ fn genBinOp( | ... | @@ -4568,7 +4583,13 @@ fn genBinOp( |
| 4568 | }; | 4583 | }; |
| 4569 | | 4584 | |
| 4570 | const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*)); | 4585 | const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*)); |
| 4571 | switch (dst_mcv) { | 4586 | const tmp_reg = switch (dst_mcv) { |
| | 4587 | .register => |reg| reg, |
| | 4588 | else => try self.copyToTmpRegister(lhs_ty, dst_mcv), |
| | 4589 | }; |
| | 4590 | const tmp_lock = self.register_manager.lockReg(tmp_reg); |
| | 4591 | defer if (tmp_lock) |lock| self.register_manager.unlockReg(lock); |
| | 4592 | switch (mat_src_mcv) { |
| 4572 | .none, | 4593 | .none, |
| 4573 | .undef, | 4594 | .undef, |
| 4574 | .dead, | 4595 | .dead, |
| ... | @@ -4576,57 +4597,44 @@ fn genBinOp( | ... | @@ -4576,57 +4597,44 @@ fn genBinOp( |
| 4576 | .immediate, | 4597 | .immediate, |
| 4577 | .eflags, | 4598 | .eflags, |
| 4578 | .register_overflow, | 4599 | .register_overflow, |
| 4579 | .stack_offset, | | |
| 4580 | .ptr_stack_offset, | 4600 | .ptr_stack_offset, |
| 4581 | .memory, | | |
| 4582 | .linker_load, | | |
| 4583 | => unreachable, | 4601 | => unreachable, |
| 4584 | .register => |dst_reg| switch (mat_src_mcv) { | 4602 | .register => |src_reg| try self.asmCmovccRegisterRegister( |
| 4585 | .none, | 4603 | registerAlias(tmp_reg, abi_size), |
| 4586 | .undef, | 4604 | registerAlias(src_reg, abi_size), |
| 4587 | .dead, | 4605 | cc, |
| 4588 | .unreach, | 4606 | ), |
| 4589 | .immediate, | 4607 | .stack_offset => |off| try self.asmCmovccRegisterMemory( |
| 4590 | .eflags, | 4608 | registerAlias(tmp_reg, abi_size), |
| 4591 | .register_overflow, | 4609 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 4592 | .ptr_stack_offset, | 4610 | .base = .rbp, |
| 4593 | => unreachable, | 4611 | .disp = -off, |
| 4594 | .register => |src_reg| try self.asmCmovccRegisterRegister( | 4612 | }), |
| 4595 | registerAlias(dst_reg, abi_size), | 4613 | cc, |
| 4596 | registerAlias(src_reg, abi_size), | 4614 | ), |
| 4597 | cc, | 4615 | .memory, .linker_load => { |
| 4598 | ), | 4616 | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 4599 | .stack_offset => |off| try self.asmCmovccRegisterMemory( | 4617 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 4600 | registerAlias(dst_reg, abi_size), | 4618 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 4601 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ | | |
| 4602 | .base = .rbp, | | |
| 4603 | .disp = -off, | | |
| 4604 | }), | | |
| 4605 | cc, | | |
| 4606 | ), | | |
| 4607 | .memory, .linker_load => { | | |
| 4608 | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); | | |
| 4609 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); | | |
| 4610 | defer self.register_manager.unlockReg(addr_reg_lock); | | |
| 4611 | | 4619 | |
| 4612 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_mcv); | 4620 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, mat_src_mcv); |
| 4613 | | 4621 | |
| 4614 | // To get the actual address of the value we want to modify we | 4622 | // To get the actual address of the value we want to modify we |
| 4615 | // we have to go through the GOT | 4623 | // we have to go through the GOT |
| 4616 | try self.asmRegisterMemory( | 4624 | try self.asmRegisterMemory( |
| 4617 | .mov, | 4625 | .mov, |
| 4618 | addr_reg, | 4626 | addr_reg, |
| 4619 | Memory.sib(.qword, .{ .base = addr_reg }), | 4627 | Memory.sib(.qword, .{ .base = addr_reg }), |
| 4620 | ); | 4628 | ); |
| 4621 | | 4629 | |
| 4622 | try self.asmCmovccRegisterMemory( | 4630 | try self.asmCmovccRegisterMemory( |
| 4623 | registerAlias(dst_reg, abi_size), | 4631 | registerAlias(tmp_reg, abi_size), |
| 4624 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = addr_reg }), | 4632 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = addr_reg }), |
| 4625 | cc, | 4633 | cc, |
| 4626 | ); | 4634 | ); |
| 4627 | }, | | |
| 4628 | }, | 4635 | }, |
| 4629 | } | 4636 | } |
| | 4637 | try self.setRegOrMem(lhs_ty, dst_mcv, .{ .register = tmp_reg }); |
| 4630 | }, | 4638 | }, |
| 4631 | .Float => try self.genBinOpMir(switch (lhs_ty.tag()) { | 4639 | .Float => try self.genBinOpMir(switch (lhs_ty.tag()) { |
| 4632 | .f32 => switch (tag) { | 4640 | .f32 => switch (tag) { |
| ... | @@ -4649,8 +4657,8 @@ fn genBinOp( | ... | @@ -4649,8 +4657,8 @@ fn genBinOp( |
| 4649 | return dst_mcv; | 4657 | return dst_mcv; |
| 4650 | } | 4658 | } |
| 4651 | | 4659 | |
| 4652 | fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void { | 4660 | fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void { |
| 4653 | const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*)); | 4661 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 4654 | switch (dst_mcv) { | 4662 | switch (dst_mcv) { |
| 4655 | .none => unreachable, | 4663 | .none => unreachable, |
| 4656 | .undef => unreachable, | 4664 | .undef => unreachable, |
| ... | @@ -4667,12 +4675,12 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -4667,12 +4675,12 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 4667 | const dst_reg_lock = self.register_manager.lockReg(dst_reg); | 4675 | const dst_reg_lock = self.register_manager.lockReg(dst_reg); |
| 4668 | defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock); | 4676 | defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock); |
| 4669 | | 4677 | |
| 4670 | const reg = try self.copyToTmpRegister(dst_ty, src_mcv); | 4678 | const reg = try self.copyToTmpRegister(ty, src_mcv); |
| 4671 | return self.genBinOpMir(mir_tag, dst_ty, dst_mcv, .{ .register = reg }); | 4679 | return self.genBinOpMir(mir_tag, ty, dst_mcv, .{ .register = reg }); |
| 4672 | }, | 4680 | }, |
| 4673 | .register => |src_reg| switch (dst_ty.zigTypeTag()) { | 4681 | .register => |src_reg| switch (ty.zigTypeTag()) { |
| 4674 | .Float => { | 4682 | .Float => { |
| 4675 | if (intrinsicsAllowed(self.target.*, dst_ty)) { | 4683 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 4676 | return self.asmRegisterRegister(mir_tag, dst_reg.to128(), src_reg.to128()); | 4684 | return self.asmRegisterRegister(mir_tag, dst_reg.to128(), src_reg.to128()); |
| 4677 | } | 4685 | } |
| 4678 | | 4686 | |
| ... | @@ -4685,7 +4693,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -4685,7 +4693,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 4685 | ), | 4693 | ), |
| 4686 | }, | 4694 | }, |
| 4687 | .immediate => |imm| { | 4695 | .immediate => |imm| { |
| 4688 | switch (self.regBitSize(dst_ty)) { | 4696 | switch (self.regBitSize(ty)) { |
| 4689 | 8, 16, 32 => { | 4697 | 8, 16, 32 => { |
| 4690 | try self.asmRegisterImmediate( | 4698 | try self.asmRegisterImmediate( |
| 4691 | mir_tag, | 4699 | mir_tag, |
| ... | @@ -4704,7 +4712,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -4704,7 +4712,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 4704 | try self.asmRegisterRegister( | 4712 | try self.asmRegisterRegister( |
| 4705 | mir_tag, | 4713 | mir_tag, |
| 4706 | registerAlias(dst_reg, abi_size), | 4714 | registerAlias(dst_reg, abi_size), |
| 4707 | registerAlias(try self.copyToTmpRegister(dst_ty, src_mcv), abi_size), | 4715 | registerAlias(try self.copyToTmpRegister(ty, src_mcv), abi_size), |
| 4708 | ); | 4716 | ); |
| 4709 | } | 4717 | } |
| 4710 | }, | 4718 | }, |
| ... | @@ -4719,8 +4727,8 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -4719,8 +4727,8 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 4719 | const dst_reg_lock = self.register_manager.lockReg(dst_reg); | 4727 | const dst_reg_lock = self.register_manager.lockReg(dst_reg); |
| 4720 | defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock); | 4728 | defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock); |
| 4721 | | 4729 | |
| 4722 | const reg = try self.copyToTmpRegister(dst_ty, src_mcv); | 4730 | const reg = try self.copyToTmpRegister(ty, src_mcv); |
| 4723 | return self.genBinOpMir(mir_tag, dst_ty, dst_mcv, .{ .register = reg }); | 4731 | return self.genBinOpMir(mir_tag, ty, dst_mcv, .{ .register = reg }); |
| 4724 | }, | 4732 | }, |
| 4725 | .stack_offset => |off| { | 4733 | .stack_offset => |off| { |
| 4726 | if (off > math.maxInt(i32)) { | 4734 | if (off > math.maxInt(i32)) { |
| ... | @@ -4754,7 +4762,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -4754,7 +4762,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 4754 | }), registerAlias(src_reg, abi_size)); | 4762 | }), registerAlias(src_reg, abi_size)); |
| 4755 | }, | 4763 | }, |
| 4756 | .immediate => |imm| { | 4764 | .immediate => |imm| { |
| 4757 | switch (self.regBitSize(dst_ty)) { | 4765 | switch (self.regBitSize(ty)) { |
| 4758 | 8, 16, 32 => { | 4766 | 8, 16, 32 => { |
| 4759 | try self.asmMemoryImmediate( | 4767 | try self.asmMemoryImmediate( |
| 4760 | mir_tag, | 4768 | mir_tag, |
| ... | @@ -4785,7 +4793,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -4785,7 +4793,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 4785 | .base = .rbp, | 4793 | .base = .rbp, |
| 4786 | .disp = -off, | 4794 | .disp = -off, |
| 4787 | }), | 4795 | }), |
| 4788 | registerAlias(try self.copyToTmpRegister(dst_ty, src_mcv), abi_size), | 4796 | registerAlias(try self.copyToTmpRegister(ty, src_mcv), abi_size), |
| 4789 | ); | 4797 | ); |
| 4790 | } | 4798 | } |
| 4791 | }, | 4799 | }, |
| ... | @@ -4793,16 +4801,18 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -4793,16 +4801,18 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 4793 | } | 4801 | } |
| 4794 | }, | 4802 | }, |
| 4795 | .memory, | 4803 | .memory, |
| | 4804 | .linker_load, |
| 4796 | .stack_offset, | 4805 | .stack_offset, |
| 4797 | .ptr_stack_offset, | 4806 | .ptr_stack_offset, |
| | 4807 | .eflags, |
| 4798 | => { | 4808 | => { |
| 4799 | return self.fail("TODO implement x86 genBinOpMir source memory", .{}); | 4809 | assert(abi_size <= 8); |
| 4800 | }, | 4810 | |
| 4801 | .linker_load => { | 4811 | const tmp_reg = try self.copyToTmpRegister(ty, src_mcv); |
| 4802 | return self.fail("TODO implement x86 genBinOpMir source symbol at index in linker", .{}); | 4812 | const tmp_lock = self.register_manager.lockReg(tmp_reg); |
| 4803 | }, | 4813 | defer if (tmp_lock) |lock| self.register_manager.unlockReg(lock); |
| 4804 | .eflags => { | 4814 | |
| 4805 | return self.fail("TODO implement x86 genBinOpMir source eflags", .{}); | 4815 | return self.genBinOpMir(mir_tag, ty, dst_mcv, .{ .register = tmp_reg }); |
| 4806 | }, | 4816 | }, |
| 4807 | } | 4817 | } |
| 4808 | }, | 4818 | }, |
| ... | @@ -7151,7 +7161,15 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -7151,7 +7161,15 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7151 | | 7161 | |
| 7152 | fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { | 7162 | fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 7153 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 7163 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 7154 | const result = try self.resolveInst(un_op); | 7164 | const result = if (self.liveness.isUnused(inst)) .dead else result: { |
| | 7165 | const src_mcv = try self.resolveInst(un_op); |
| | 7166 | if (self.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv; |
| | 7167 | |
| | 7168 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| | 7169 | const dst_ty = self.air.typeOfIndex(inst); |
| | 7170 | try self.setRegOrMem(dst_ty, dst_mcv, src_mcv); |
| | 7171 | break :result dst_mcv; |
| | 7172 | }; |
| 7155 | return self.finishAir(inst, result, .{ un_op, .none, .none }); | 7173 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 7156 | } | 7174 | } |
| 7157 | | 7175 | |