| ... | @@ -731,6 +731,40 @@ fn asmMemoryRegisterImmediate( | ... | @@ -731,6 +731,40 @@ fn asmMemoryRegisterImmediate( |
| 731 | }); | 731 | }); |
| 732 | } | 732 | } |
| 733 | | 733 | |
| | 734 | fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codegen.LinkerLoad) !void { |
| | 735 | const ops: Mir.Inst.Ops = switch (linker_load.type) { |
| | 736 | .got => .got_reloc, |
| | 737 | .direct => .direct_reloc, |
| | 738 | .import => .import_reloc, |
| | 739 | }; |
| | 740 | _ = try self.addInst(.{ |
| | 741 | .tag = .mov_linker, |
| | 742 | .ops = ops, |
| | 743 | .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{ |
| | 744 | .reg = @enumToInt(reg), |
| | 745 | .atom_index = atom_index, |
| | 746 | .sym_index = linker_load.sym_index, |
| | 747 | }) }, |
| | 748 | }); |
| | 749 | } |
| | 750 | |
| | 751 | fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codegen.LinkerLoad) !void { |
| | 752 | const ops: Mir.Inst.Ops = switch (linker_load.type) { |
| | 753 | .got => .got_reloc, |
| | 754 | .direct => .direct_reloc, |
| | 755 | .import => .import_reloc, |
| | 756 | }; |
| | 757 | _ = try self.addInst(.{ |
| | 758 | .tag = .lea_linker, |
| | 759 | .ops = ops, |
| | 760 | .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{ |
| | 761 | .reg = @enumToInt(reg), |
| | 762 | .atom_index = atom_index, |
| | 763 | .sym_index = linker_load.sym_index, |
| | 764 | }) }, |
| | 765 | }); |
| | 766 | } |
| | 767 | |
| 734 | fn gen(self: *Self) InnerError!void { | 768 | fn gen(self: *Self) InnerError!void { |
| 735 | const cc = self.fn_type.fnCallingConvention(); | 769 | const cc = self.fn_type.fnCallingConvention(); |
| 736 | if (cc != .Naked) { | 770 | if (cc != .Naked) { |
| ... | @@ -7454,10 +7488,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -7454,10 +7488,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7454 | | 7488 | |
| 7455 | try self.asmRegisterRegister(.mov, registerAlias(reg, abi_size), registerAlias(src_reg, abi_size)); | 7489 | try self.asmRegisterRegister(.mov, registerAlias(reg, abi_size), registerAlias(src_reg, abi_size)); |
| 7456 | }, | 7490 | }, |
| 7457 | .memory, .linker_load => switch (ty.zigTypeTag()) { | 7491 | .memory => |addr| switch (ty.zigTypeTag()) { |
| 7458 | .Float => { | 7492 | .Float => { |
| 7459 | const base_reg = try self.register_manager.allocReg(null, gp); | 7493 | const base_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 7460 | try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv); | 7494 | try self.genSetReg(Type.usize, base_reg, .{ .immediate = addr }); |
| 7461 | | 7495 | |
| 7462 | if (intrinsicsAllowed(self.target.*, ty)) { | 7496 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 7463 | return self.asmRegisterMemory( | 7497 | return self.asmRegisterMemory( |
| ... | @@ -7469,29 +7503,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -7469,29 +7503,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7469 | }), | 7503 | }), |
| 7470 | }, | 7504 | }, |
| 7471 | reg.to128(), | 7505 | reg.to128(), |
| 7472 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg.to64() }), | 7506 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg }), |
| 7473 | ); | 7507 | ); |
| 7474 | } | 7508 | } |
| 7475 | | 7509 | |
| 7476 | return self.fail("TODO genSetReg from memory for float with no intrinsics", .{}); | 7510 | return self.fail("TODO genSetReg from memory for float with no intrinsics", .{}); |
| 7477 | }, | 7511 | }, |
| 7478 | else => switch (mcv) { | 7512 | else => { |
| 7479 | else => unreachable, | 7513 | if (addr <= math.maxInt(i32)) { |
| 7480 | .linker_load => { | | |
| 7481 | try self.loadMemPtrIntoRegister(reg, Type.usize, mcv); | | |
| 7482 | try self.asmRegisterMemory( | | |
| 7483 | .mov, | | |
| 7484 | registerAlias(reg, abi_size), | | |
| 7485 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }), | | |
| 7486 | ); | | |
| 7487 | }, | | |
| 7488 | .memory => |x| if (x <= math.maxInt(i32)) { | | |
| 7489 | try self.asmRegisterMemory( | 7514 | try self.asmRegisterMemory( |
| 7490 | .mov, | 7515 | .mov, |
| 7491 | registerAlias(reg, abi_size), | 7516 | registerAlias(reg, abi_size), |
| 7492 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ | 7517 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 7493 | .base = .ds, | 7518 | .base = .ds, |
| 7494 | .disp = @intCast(i32, x), | 7519 | .disp = @intCast(i32, addr), |
| 7495 | }), | 7520 | }), |
| 7496 | ); | 7521 | ); |
| 7497 | } else { | 7522 | } else { |
| ... | @@ -7501,20 +7526,53 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -7501,20 +7526,53 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7501 | _ = try self.addInst(.{ | 7526 | _ = try self.addInst(.{ |
| 7502 | .tag = .mov_moffs, | 7527 | .tag = .mov_moffs, |
| 7503 | .ops = .rax_moffs, | 7528 | .ops = .rax_moffs, |
| 7504 | .data = .{ .payload = try self.addExtra(Mir.MemoryMoffs.encode(.ds, x)) }, | 7529 | .data = .{ .payload = try self.addExtra(Mir.MemoryMoffs.encode(.ds, addr)) }, |
| 7505 | }); | 7530 | }); |
| 7506 | } else { | 7531 | } else { |
| 7507 | // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue. | 7532 | // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue. |
| 7508 | try self.genSetReg(ty, reg, MCValue{ .immediate = x }); | 7533 | try self.genSetReg(Type.usize, reg, MCValue{ .immediate = addr }); |
| 7509 | try self.asmRegisterMemory( | 7534 | try self.asmRegisterMemory( |
| 7510 | .mov, | 7535 | .mov, |
| 7511 | registerAlias(reg, abi_size), | 7536 | registerAlias(reg, abi_size), |
| 7512 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }), | 7537 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }), |
| 7513 | ); | 7538 | ); |
| 7514 | } | 7539 | } |
| 7515 | }, | 7540 | } |
| 7516 | }, | 7541 | }, |
| 7517 | }, | 7542 | }, |
| | 7543 | .linker_load => |load_struct| { |
| | 7544 | const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: { |
| | 7545 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| | 7546 | break :blk macho_file.getAtom(atom).getSymbolIndex().?; |
| | 7547 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: { |
| | 7548 | const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| | 7549 | break :blk coff_file.getAtom(atom).getSymbolIndex().?; |
| | 7550 | } else unreachable; |
| | 7551 | |
| | 7552 | switch (ty.zigTypeTag()) { |
| | 7553 | .Float => { |
| | 7554 | const base_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| | 7555 | try self.asmLeaLinker(base_reg, atom_index, load_struct); |
| | 7556 | |
| | 7557 | if (intrinsicsAllowed(self.target.*, ty)) { |
| | 7558 | return self.asmRegisterMemory( |
| | 7559 | switch (ty.tag()) { |
| | 7560 | .f32 => .movss, |
| | 7561 | .f64 => .movsd, |
| | 7562 | else => return self.fail("TODO genSetReg from memory for {}", .{ |
| | 7563 | ty.fmt(self.bin_file.options.module.?), |
| | 7564 | }), |
| | 7565 | }, |
| | 7566 | reg.to128(), |
| | 7567 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base_reg.to64() }), |
| | 7568 | ); |
| | 7569 | } |
| | 7570 | |
| | 7571 | return self.fail("TODO genSetReg from memory for float with no intrinsics", .{}); |
| | 7572 | }, |
| | 7573 | else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct), |
| | 7574 | } |
| | 7575 | }, |
| 7518 | .stack_offset => |off| { | 7576 | .stack_offset => |off| { |
| 7519 | switch (ty.zigTypeTag()) { | 7577 | switch (ty.zigTypeTag()) { |
| 7520 | .Int => switch (ty.intInfo(self.target.*).signedness) { | 7578 | .Int => switch (ty.intInfo(self.target.*).signedness) { |