| ... | ... | @@ -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 | 768 | fn gen(self: *Self) InnerError!void { |
| 735 | 769 | const cc = self.fn_type.fnCallingConvention(); |
| 736 | 770 | if (cc != .Naked) { |
| ... | ... | @@ -7454,10 +7488,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7454 | 7488 | |
| 7455 | 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 | 7492 | .Float => { |
| 7459 | | const base_reg = try self.register_manager.allocReg(null, gp); |
| 7460 | | try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv); |
| 7493 | const base_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 7494 | try self.genSetReg(Type.usize, base_reg, .{ .immediate = addr }); |
| 7461 | 7495 | |
| 7462 | 7496 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 7463 | 7497 | return self.asmRegisterMemory( |
| ... | ... | @@ -7469,29 +7503,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7469 | 7503 | }), |
| 7470 | 7504 | }, |
| 7471 | 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 | 7510 | return self.fail("TODO genSetReg from memory for float with no intrinsics", .{}); |
| 7477 | 7511 | }, |
| 7478 | | else => switch (mcv) { |
| 7479 | | else => unreachable, |
| 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)) { |
| 7512 | else => { |
| 7513 | if (addr <= math.maxInt(i32)) { |
| 7489 | 7514 | try self.asmRegisterMemory( |
| 7490 | 7515 | .mov, |
| 7491 | 7516 | registerAlias(reg, abi_size), |
| 7492 | 7517 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 7493 | 7518 | .base = .ds, |
| 7494 | | .disp = @intCast(i32, x), |
| 7519 | .disp = @intCast(i32, addr), |
| 7495 | 7520 | }), |
| 7496 | 7521 | ); |
| 7497 | 7522 | } else { |
| ... | ... | @@ -7501,20 +7526,53 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7501 | 7526 | _ = try self.addInst(.{ |
| 7502 | 7527 | .tag = .mov_moffs, |
| 7503 | 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 | 7531 | } else { |
| 7507 | 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 | 7534 | try self.asmRegisterMemory( |
| 7510 | 7535 | .mov, |
| 7511 | 7536 | registerAlias(reg, abi_size), |
| 7512 | 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 | 7576 | .stack_offset => |off| { |
| 7519 | 7577 | switch (ty.zigTypeTag()) { |
| 7520 | 7578 | .Int => switch (ty.intInfo(self.target.*).signedness) { |