| ... | ... | @@ -2346,7 +2346,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2346 | 2346 | return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }, .{}); |
| 2347 | 2347 | } |
| 2348 | 2348 | |
| 2349 | | try self.genInlineMemcpy(off, elem_ty, ptr, .{}); |
| 2349 | try self.genInlineMemcpy(dst_mcv, ptr, .{ .immediate = abi_size }, .{}); |
| 2350 | 2350 | }, |
| 2351 | 2351 | else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}), |
| 2352 | 2352 | } |
| ... | ... | @@ -2392,6 +2392,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue |
| 2392 | 2392 | .got_load, |
| 2393 | 2393 | .direct_load, |
| 2394 | 2394 | => |sym_index| { |
| 2395 | const abi_size = @intCast(u32, ptr_ty.abiSize(self.target.*)); |
| 2395 | 2396 | const flags: u2 = switch (ptr) { |
| 2396 | 2397 | .got_load => 0b00, |
| 2397 | 2398 | .direct_load => 0b01, |
| ... | ... | @@ -2400,7 +2401,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue |
| 2400 | 2401 | _ = try self.addInst(.{ |
| 2401 | 2402 | .tag = .lea_pie, |
| 2402 | 2403 | .ops = (Mir.Ops{ |
| 2403 | | .reg1 = registerAlias(reg, @intCast(u32, ptr_ty.abiSize(self.target.*))), |
| 2404 | .reg1 = registerAlias(reg, abi_size), |
| 2404 | 2405 | .flags = flags, |
| 2405 | 2406 | }).encode(), |
| 2406 | 2407 | .data = .{ |
| ... | ... | @@ -2524,7 +2525,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2524 | 2525 | return self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); |
| 2525 | 2526 | } |
| 2526 | 2527 | |
| 2527 | | try self.genInlineMemcpy(0, value_ty, value, .{ |
| 2528 | try self.genInlineMemcpy(.{ .stack_offset = 0 }, value, .{ .immediate = abi_size }, .{ |
| 2528 | 2529 | .source_stack_base = .rbp, |
| 2529 | 2530 | .dest_stack_base = reg.to64(), |
| 2530 | 2531 | }); |
| ... | ... | @@ -3464,7 +3465,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 3464 | 3465 | .data = undefined, |
| 3465 | 3466 | }); |
| 3466 | 3467 | try self.ret_backpatches.append(self.gpa, backpatch); |
| 3467 | | try self.genInlineMemcpy(0, elem_ty, ptr, .{ |
| 3468 | try self.genInlineMemcpy(.{ .stack_offset = 0 }, ptr, .{ .immediate = elem_ty.abiSize(self.target.*) }, .{ |
| 3468 | 3469 | .source_stack_base = .rbp, |
| 3469 | 3470 | .dest_stack_base = reg, |
| 3470 | 3471 | }); |
| ... | ... | @@ -4412,9 +4413,12 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 4412 | 4413 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 4413 | 4414 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 4414 | 4415 | } |
| 4415 | | try self.genInlineMemset(stack_offset, ty, .{ .immediate = 0xaa }, .{ |
| 4416 | | .dest_stack_base = .rsp, |
| 4417 | | }); |
| 4416 | try self.genInlineMemset( |
| 4417 | .{ .stack_offset = stack_offset }, |
| 4418 | .{ .immediate = 0xaa }, |
| 4419 | .{ .immediate = abi_size }, |
| 4420 | .{ .dest_stack_base = .rsp }, |
| 4421 | ); |
| 4418 | 4422 | }, |
| 4419 | 4423 | .compare_flags_unsigned, |
| 4420 | 4424 | .compare_flags_signed, |
| ... | ... | @@ -4469,7 +4473,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 4469 | 4473 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 4470 | 4474 | } |
| 4471 | 4475 | |
| 4472 | | try self.genInlineMemcpy(stack_offset, ty, mcv, .{ |
| 4476 | try self.genInlineMemcpy(.{ .stack_offset = stack_offset }, mcv, .{ .immediate = abi_size }, .{ |
| 4473 | 4477 | .source_stack_base = .rbp, |
| 4474 | 4478 | .dest_stack_base = .rsp, |
| 4475 | 4479 | }); |
| ... | ... | @@ -4495,7 +4499,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 4495 | 4499 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 4496 | 4500 | } |
| 4497 | 4501 | |
| 4498 | | try self.genInlineMemcpy(stack_offset, ty, mcv, .{ |
| 4502 | try self.genInlineMemcpy(.{ .stack_offset = stack_offset }, mcv, .{ .immediate = abi_size }, .{ |
| 4499 | 4503 | .source_stack_base = .rbp, |
| 4500 | 4504 | .dest_stack_base = .rsp, |
| 4501 | 4505 | }); |
| ... | ... | @@ -4518,7 +4522,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 4518 | 4522 | 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }, opts), |
| 4519 | 4523 | 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }, opts), |
| 4520 | 4524 | 8 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa }, opts), |
| 4521 | | else => return self.genInlineMemset(stack_offset, ty, .{ .immediate = 0xaa }, opts), |
| 4525 | else => |x| return self.genInlineMemset( |
| 4526 | .{ .stack_offset = stack_offset }, |
| 4527 | .{ .immediate = 0xaa }, |
| 4528 | .{ .immediate = x }, |
| 4529 | opts, |
| 4530 | ), |
| 4522 | 4531 | } |
| 4523 | 4532 | }, |
| 4524 | 4533 | .compare_flags_unsigned, |
| ... | ... | @@ -4650,7 +4659,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 4650 | 4659 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts); |
| 4651 | 4660 | } |
| 4652 | 4661 | |
| 4653 | | try self.genInlineMemcpy(stack_offset, ty, mcv, opts); |
| 4662 | try self.genInlineMemcpy(.{ .stack_offset = stack_offset }, mcv, .{ .immediate = abi_size }, opts); |
| 4654 | 4663 | }, |
| 4655 | 4664 | .ptr_stack_offset => { |
| 4656 | 4665 | const reg = try self.copyToTmpRegister(ty, mcv); |
| ... | ... | @@ -4667,7 +4676,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 4667 | 4676 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts); |
| 4668 | 4677 | } |
| 4669 | 4678 | |
| 4670 | | try self.genInlineMemcpy(stack_offset, ty, mcv, opts); |
| 4679 | try self.genInlineMemcpy(.{ .stack_offset = stack_offset }, mcv, .{ .immediate = abi_size }, opts); |
| 4671 | 4680 | }, |
| 4672 | 4681 | } |
| 4673 | 4682 | } |
| ... | ... | @@ -4677,9 +4686,13 @@ const InlineMemcpyOpts = struct { |
| 4677 | 4686 | dest_stack_base: ?Register = null, |
| 4678 | 4687 | }; |
| 4679 | 4688 | |
| 4680 | | fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: InlineMemcpyOpts) InnerError!void { |
| 4681 | | const abi_size = ty.abiSize(self.target.*); |
| 4682 | | |
| 4689 | fn genInlineMemcpy( |
| 4690 | self: *Self, |
| 4691 | dst_ptr: MCValue, |
| 4692 | src_ptr: MCValue, |
| 4693 | len: MCValue, |
| 4694 | opts: InlineMemcpyOpts, |
| 4695 | ) InnerError!void { |
| 4683 | 4696 | // TODO this is wrong. We should check first if any of the operands is in `.rax` or `.rcx` before |
| 4684 | 4697 | // spilling. Consolidate with other TODOs regarding register allocation mechanics. |
| 4685 | 4698 | try self.register_manager.getReg(.rax, null); |
| ... | ... | @@ -4694,19 +4707,55 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: |
| 4694 | 4707 | if (opts.dest_stack_base) |reg| self.register_manager.freezeRegs(&.{reg}); |
| 4695 | 4708 | defer if (opts.dest_stack_base) |reg| self.register_manager.unfreezeRegs(&.{reg}); |
| 4696 | 4709 | |
| 4697 | | const addr_reg = try self.register_manager.allocReg(null); |
| 4698 | | switch (val) { |
| 4710 | const dst_addr_reg = try self.register_manager.allocReg(null); |
| 4711 | switch (dst_ptr) { |
| 4699 | 4712 | .memory, |
| 4713 | .got_load, |
| 4700 | 4714 | .direct_load, |
| 4715 | => { |
| 4716 | try self.loadMemPtrIntoRegister(dst_addr_reg, Type.usize, dst_ptr); |
| 4717 | }, |
| 4718 | .ptr_stack_offset, .stack_offset => |off| { |
| 4719 | _ = try self.addInst(.{ |
| 4720 | .tag = .lea, |
| 4721 | .ops = (Mir.Ops{ |
| 4722 | .reg1 = dst_addr_reg.to64(), |
| 4723 | .reg2 = opts.dest_stack_base orelse .rbp, |
| 4724 | }).encode(), |
| 4725 | .data = .{ .imm = @bitCast(u32, -off) }, |
| 4726 | }); |
| 4727 | }, |
| 4728 | .register => |reg| { |
| 4729 | _ = try self.addInst(.{ |
| 4730 | .tag = .mov, |
| 4731 | .ops = (Mir.Ops{ |
| 4732 | .reg1 = registerAlias(dst_addr_reg, @divExact(reg.size(), 8)), |
| 4733 | .reg2 = reg, |
| 4734 | }).encode(), |
| 4735 | .data = undefined, |
| 4736 | }); |
| 4737 | }, |
| 4738 | else => { |
| 4739 | return self.fail("TODO implement memcpy for setting stack when dest is {}", .{dst_ptr}); |
| 4740 | }, |
| 4741 | } |
| 4742 | |
| 4743 | self.register_manager.freezeRegs(&.{dst_addr_reg}); |
| 4744 | defer self.register_manager.unfreezeRegs(&.{dst_addr_reg}); |
| 4745 | |
| 4746 | const src_addr_reg = try self.register_manager.allocReg(null); |
| 4747 | switch (src_ptr) { |
| 4748 | .memory, |
| 4701 | 4749 | .got_load, |
| 4750 | .direct_load, |
| 4702 | 4751 | => { |
| 4703 | | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, val); |
| 4752 | try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr); |
| 4704 | 4753 | }, |
| 4705 | 4754 | .ptr_stack_offset, .stack_offset => |off| { |
| 4706 | 4755 | _ = try self.addInst(.{ |
| 4707 | 4756 | .tag = .lea, |
| 4708 | 4757 | .ops = (Mir.Ops{ |
| 4709 | | .reg1 = addr_reg.to64(), |
| 4758 | .reg1 = src_addr_reg.to64(), |
| 4710 | 4759 | .reg2 = opts.source_stack_base orelse .rbp, |
| 4711 | 4760 | }).encode(), |
| 4712 | 4761 | .data = .{ .imm = @bitCast(u32, -off) }, |
| ... | ... | @@ -4716,25 +4765,25 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: |
| 4716 | 4765 | _ = try self.addInst(.{ |
| 4717 | 4766 | .tag = .mov, |
| 4718 | 4767 | .ops = (Mir.Ops{ |
| 4719 | | .reg1 = registerAlias(addr_reg, @divExact(reg.size(), 8)), |
| 4768 | .reg1 = registerAlias(src_addr_reg, @divExact(reg.size(), 8)), |
| 4720 | 4769 | .reg2 = reg, |
| 4721 | 4770 | }).encode(), |
| 4722 | 4771 | .data = undefined, |
| 4723 | 4772 | }); |
| 4724 | 4773 | }, |
| 4725 | 4774 | else => { |
| 4726 | | return self.fail("TODO implement memcpy for setting stack from {}", .{val}); |
| 4775 | return self.fail("TODO implement memcpy for setting stack when src is {}", .{src_ptr}); |
| 4727 | 4776 | }, |
| 4728 | 4777 | } |
| 4729 | 4778 | |
| 4730 | | self.register_manager.freezeRegs(&.{addr_reg}); |
| 4731 | | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| 4779 | self.register_manager.freezeRegs(&.{src_addr_reg}); |
| 4780 | defer self.register_manager.unfreezeRegs(&.{src_addr_reg}); |
| 4732 | 4781 | |
| 4733 | 4782 | const regs = try self.register_manager.allocRegs(2, .{ null, null }); |
| 4734 | 4783 | const count_reg = regs[0].to64(); |
| 4735 | 4784 | const tmp_reg = regs[1].to8(); |
| 4736 | 4785 | |
| 4737 | | try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) }); |
| 4786 | try self.genSetReg(Type.usize, count_reg, len); |
| 4738 | 4787 | |
| 4739 | 4788 | // mov rcx, 0 |
| 4740 | 4789 | _ = try self.addInst(.{ |
| ... | ... | @@ -4776,7 +4825,7 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: |
| 4776 | 4825 | .tag = .mov_scale_src, |
| 4777 | 4826 | .ops = (Mir.Ops{ |
| 4778 | 4827 | .reg1 = tmp_reg.to8(), |
| 4779 | | .reg2 = addr_reg, |
| 4828 | .reg2 = src_addr_reg, |
| 4780 | 4829 | }).encode(), |
| 4781 | 4830 | .data = .{ .imm = 0 }, |
| 4782 | 4831 | }); |
| ... | ... | @@ -4785,10 +4834,10 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: |
| 4785 | 4834 | _ = try self.addInst(.{ |
| 4786 | 4835 | .tag = .mov_scale_dst, |
| 4787 | 4836 | .ops = (Mir.Ops{ |
| 4788 | | .reg1 = opts.dest_stack_base orelse .rbp, |
| 4837 | .reg1 = dst_addr_reg, |
| 4789 | 4838 | .reg2 = tmp_reg.to8(), |
| 4790 | 4839 | }).encode(), |
| 4791 | | .data = .{ .imm = @bitCast(u32, -stack_offset) }, |
| 4840 | .data = .{ .imm = 0 }, |
| 4792 | 4841 | }); |
| 4793 | 4842 | |
| 4794 | 4843 | // add rcx, 1 |
| ... | ... | @@ -4831,39 +4880,52 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: |
| 4831 | 4880 | |
| 4832 | 4881 | fn genInlineMemset( |
| 4833 | 4882 | self: *Self, |
| 4834 | | stack_offset: i32, |
| 4835 | | ty: Type, |
| 4883 | dst_ptr: MCValue, |
| 4836 | 4884 | value: MCValue, |
| 4885 | len: MCValue, |
| 4837 | 4886 | opts: InlineMemcpyOpts, |
| 4838 | 4887 | ) InnerError!void { |
| 4839 | 4888 | try self.register_manager.getReg(.rax, null); |
| 4889 | self.register_manager.freezeRegs(&.{.rax}); |
| 4890 | defer self.register_manager.unfreezeRegs(&.{.rax}); |
| 4840 | 4891 | |
| 4841 | | const abi_size = ty.abiSize(self.target.*); |
| 4842 | | const negative_offset = @bitCast(u32, -stack_offset); |
| 4843 | | |
| 4844 | | // We are actually counting `abi_size` bytes; however, we reuse the index register |
| 4845 | | // as both the counter and offset scaler, hence we need to subtract one from `abi_size` |
| 4846 | | // and count until -1. |
| 4847 | | if (abi_size > math.maxInt(i32)) { |
| 4848 | | // movabs rax, abi_size - 1 |
| 4849 | | const payload = try self.addExtra(Mir.Imm64.encode(abi_size - 1)); |
| 4850 | | _ = try self.addInst(.{ |
| 4851 | | .tag = .movabs, |
| 4852 | | .ops = (Mir.Ops{ |
| 4853 | | .reg1 = .rax, |
| 4854 | | }).encode(), |
| 4855 | | .data = .{ .payload = payload }, |
| 4856 | | }); |
| 4857 | | } else { |
| 4858 | | // mov rax, abi_size - 1 |
| 4859 | | _ = try self.addInst(.{ |
| 4860 | | .tag = .mov, |
| 4861 | | .ops = (Mir.Ops{ |
| 4862 | | .reg1 = .rax, |
| 4863 | | }).encode(), |
| 4864 | | .data = .{ .imm = @truncate(u32, abi_size - 1) }, |
| 4865 | | }); |
| 4892 | const addr_reg = try self.register_manager.allocReg(null); |
| 4893 | switch (dst_ptr) { |
| 4894 | .memory, |
| 4895 | .got_load, |
| 4896 | .direct_load, |
| 4897 | => { |
| 4898 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_ptr); |
| 4899 | }, |
| 4900 | .ptr_stack_offset, .stack_offset => |off| { |
| 4901 | _ = try self.addInst(.{ |
| 4902 | .tag = .lea, |
| 4903 | .ops = (Mir.Ops{ |
| 4904 | .reg1 = addr_reg.to64(), |
| 4905 | .reg2 = opts.dest_stack_base orelse .rbp, |
| 4906 | }).encode(), |
| 4907 | .data = .{ .imm = @bitCast(u32, -off) }, |
| 4908 | }); |
| 4909 | }, |
| 4910 | .register => |reg| { |
| 4911 | _ = try self.addInst(.{ |
| 4912 | .tag = .mov, |
| 4913 | .ops = (Mir.Ops{ |
| 4914 | .reg1 = registerAlias(addr_reg, @divExact(reg.size(), 8)), |
| 4915 | .reg2 = reg, |
| 4916 | }).encode(), |
| 4917 | .data = undefined, |
| 4918 | }); |
| 4919 | }, |
| 4920 | else => { |
| 4921 | return self.fail("TODO implement memcpy for setting stack when dest is {}", .{dst_ptr}); |
| 4922 | }, |
| 4866 | 4923 | } |
| 4924 | self.register_manager.freezeRegs(&.{addr_reg}); |
| 4925 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| 4926 | |
| 4927 | try self.genSetReg(Type.usize, .rax, len); |
| 4928 | try self.genBinMathOpMir(.sub, Type.usize, .{ .register = .rax }, .{ .immediate = 1 }); |
| 4867 | 4929 | |
| 4868 | 4930 | // loop: |
| 4869 | 4931 | // cmp rax, -1 |
| ... | ... | @@ -4889,13 +4951,13 @@ fn genInlineMemset( |
| 4889 | 4951 | } |
| 4890 | 4952 | // mov byte ptr [rbp + rax + stack_offset], imm |
| 4891 | 4953 | const payload = try self.addExtra(Mir.ImmPair{ |
| 4892 | | .dest_off = negative_offset, |
| 4954 | .dest_off = 0, |
| 4893 | 4955 | .operand = @truncate(u32, x), |
| 4894 | 4956 | }); |
| 4895 | 4957 | _ = try self.addInst(.{ |
| 4896 | 4958 | .tag = .mov_mem_index_imm, |
| 4897 | 4959 | .ops = (Mir.Ops{ |
| 4898 | | .reg1 = opts.dest_stack_base orelse .rbp, |
| 4960 | .reg1 = addr_reg, |
| 4899 | 4961 | }).encode(), |
| 4900 | 4962 | .data = .{ .payload = payload }, |
| 4901 | 4963 | }); |
| ... | ... | @@ -5076,33 +5138,15 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5076 | 5138 | .data = undefined, |
| 5077 | 5139 | }); |
| 5078 | 5140 | }, |
| 5079 | | .got_load, |
| 5080 | 5141 | .direct_load, |
| 5081 | | => |sym_index| { |
| 5082 | | const flags: u2 = switch (mcv) { |
| 5083 | | .got_load => 0b00, |
| 5084 | | .direct_load => 0b01, |
| 5085 | | else => unreachable, |
| 5086 | | }; |
| 5087 | | _ = try self.addInst(.{ |
| 5088 | | .tag = .lea_pie, |
| 5089 | | .ops = (Mir.Ops{ |
| 5090 | | .reg1 = reg, |
| 5091 | | .flags = flags, |
| 5092 | | }).encode(), |
| 5093 | | .data = .{ |
| 5094 | | .load_reloc = .{ |
| 5095 | | .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index, |
| 5096 | | .sym_index = sym_index, |
| 5097 | | }, |
| 5098 | | }, |
| 5099 | | }); |
| 5100 | | // MOV reg, [reg] |
| 5142 | .got_load, |
| 5143 | => { |
| 5144 | try self.loadMemPtrIntoRegister(reg, Type.usize, mcv); |
| 5101 | 5145 | _ = try self.addInst(.{ |
| 5102 | 5146 | .tag = .mov, |
| 5103 | 5147 | .ops = (Mir.Ops{ |
| 5104 | | .reg1 = reg, |
| 5105 | | .reg2 = reg, |
| 5148 | .reg1 = reg.to64(), |
| 5149 | .reg2 = reg.to64(), |
| 5106 | 5150 | .flags = 0b01, |
| 5107 | 5151 | }).encode(), |
| 5108 | 5152 | .data = .{ .imm = 0 }, |
| ... | ... | @@ -5278,13 +5322,69 @@ fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOr |
| 5278 | 5322 | } |
| 5279 | 5323 | |
| 5280 | 5324 | fn airMemset(self: *Self, inst: Air.Inst.Index) !void { |
| 5281 | | _ = inst; |
| 5282 | | return self.fail("TODO implement airMemset for {}", .{self.target.cpu.arch}); |
| 5325 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 5326 | const extra = self.air.extraData(Air.Bin, pl_op.payload).data; |
| 5327 | |
| 5328 | const dst_ptr = try self.resolveInst(pl_op.operand); |
| 5329 | dst_ptr.freezeIfRegister(&self.register_manager); |
| 5330 | defer dst_ptr.unfreezeIfRegister(&self.register_manager); |
| 5331 | |
| 5332 | const src_val = try self.resolveInst(extra.lhs); |
| 5333 | src_val.freezeIfRegister(&self.register_manager); |
| 5334 | defer src_val.unfreezeIfRegister(&self.register_manager); |
| 5335 | |
| 5336 | const len = try self.resolveInst(extra.rhs); |
| 5337 | len.freezeIfRegister(&self.register_manager); |
| 5338 | defer len.unfreezeIfRegister(&self.register_manager); |
| 5339 | |
| 5340 | try self.genInlineMemset(dst_ptr, src_val, len, .{}); |
| 5341 | |
| 5342 | return self.finishAir(inst, .none, .{ pl_op.operand, .none, .none }); |
| 5283 | 5343 | } |
| 5284 | 5344 | |
| 5285 | 5345 | fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 5286 | | _ = inst; |
| 5287 | | return self.fail("TODO implement airMemcpy for {}", .{self.target.cpu.arch}); |
| 5346 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 5347 | const extra = self.air.extraData(Air.Bin, pl_op.payload).data; |
| 5348 | |
| 5349 | const dst_ptr = try self.resolveInst(pl_op.operand); |
| 5350 | dst_ptr.freezeIfRegister(&self.register_manager); |
| 5351 | defer dst_ptr.unfreezeIfRegister(&self.register_manager); |
| 5352 | |
| 5353 | const src_ty = self.air.typeOf(extra.lhs); |
| 5354 | const src_ptr = try self.resolveInst(extra.lhs); |
| 5355 | src_ptr.freezeIfRegister(&self.register_manager); |
| 5356 | defer src_ptr.unfreezeIfRegister(&self.register_manager); |
| 5357 | |
| 5358 | const len = try self.resolveInst(extra.rhs); |
| 5359 | len.freezeIfRegister(&self.register_manager); |
| 5360 | defer len.unfreezeIfRegister(&self.register_manager); |
| 5361 | |
| 5362 | // TODO Is this the only condition for pointer dereference for memcpy? |
| 5363 | const src: MCValue = blk: { |
| 5364 | switch (src_ptr) { |
| 5365 | .got_load, .direct_load, .memory => { |
| 5366 | const reg = try self.register_manager.allocReg(null); |
| 5367 | try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr); |
| 5368 | _ = try self.addInst(.{ |
| 5369 | .tag = .mov, |
| 5370 | .ops = (Mir.Ops{ |
| 5371 | .reg1 = reg, |
| 5372 | .reg2 = reg, |
| 5373 | .flags = 0b01, |
| 5374 | }).encode(), |
| 5375 | .data = .{ .imm = 0 }, |
| 5376 | }); |
| 5377 | break :blk MCValue{ .register = reg }; |
| 5378 | }, |
| 5379 | else => break :blk src_ptr, |
| 5380 | } |
| 5381 | }; |
| 5382 | src.freezeIfRegister(&self.register_manager); |
| 5383 | defer src.unfreezeIfRegister(&self.register_manager); |
| 5384 | |
| 5385 | try self.genInlineMemcpy(dst_ptr, src, len, .{}); |
| 5386 | |
| 5387 | return self.finishAir(inst, .none, .{ pl_op.operand, .none, .none }); |
| 5288 | 5388 | } |
| 5289 | 5389 | |
| 5290 | 5390 | fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |