authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-09 18:38:54+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-11 20:05:49+01:00
log9658ab676643ef5c2457ac4908c180e05dc7f729
tree518fbcc79bcb6886586e2dadf7cac3aa0b1a56d0
parent1bde522c2c6cae52c581458774ad1dfa479d8426

x86_64: handle all instructions without introducing Memory operand


2 files changed, 257 insertions(+), 319 deletions(-)

src/arch/x86_64/CodeGen.zig+149-316
...@@ -400,7 +400,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {...@@ -400,7 +400,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
400 return result;400 return result;
401}401}
402402
403fn asmSetCCRegister(self: *Self, reg: Register, cc: bits.Condition) !void {403fn asmSetccRegister(self: *Self, reg: Register, cc: bits.Condition) !void {
404 _ = try self.addInst(.{404 _ = try self.addInst(.{
405 .tag = .setcc,405 .tag = .setcc,
406 .ops = .r_c,406 .ops = .r_c,
...@@ -411,7 +411,7 @@ fn asmSetCCRegister(self: *Self, reg: Register, cc: bits.Condition) !void {...@@ -411,7 +411,7 @@ fn asmSetCCRegister(self: *Self, reg: Register, cc: bits.Condition) !void {
411 });411 });
412}412}
413413
414fn asmCmovCCRegisterRegister(self: *Self, reg1: Register, reg2: Register, cc: bits.Condition) !void {414fn asmCmovccRegisterRegister(self: *Self, reg1: Register, reg2: Register, cc: bits.Condition) !void {
415 _ = try self.addInst(.{415 _ = try self.addInst(.{
416 .tag = .cmovcc,416 .tag = .cmovcc,
417 .ops = .rr_c,417 .ops = .rr_c,
...@@ -1369,7 +1369,7 @@ fn airMin(self: *Self, inst: Air.Inst.Index) !void {...@@ -1369,7 +1369,7 @@ fn airMin(self: *Self, inst: Air.Inst.Index) !void {
1369 .unsigned => .b,1369 .unsigned => .b,
1370 .signed => .l,1370 .signed => .l,
1371 };1371 };
1372 try self.asmCmovCCRegisterRegister(dst_mcv.register, lhs_reg, cc);1372 try self.asmCmovccRegisterRegister(dst_mcv.register, lhs_reg, cc);
13731373
1374 break :result dst_mcv;1374 break :result dst_mcv;
1375 };1375 };
...@@ -1569,7 +1569,7 @@ fn genSetStackTruncatedOverflowCompare(...@@ -1569,7 +1569,7 @@ fn genSetStackTruncatedOverflowCompare(
1569 .signed => .o,1569 .signed => .o,
1570 .unsigned => .c,1570 .unsigned => .c,
1571 };1571 };
1572 try self.asmSetCCRegister(overflow_reg.to8(), cc);1572 try self.asmSetccRegister(overflow_reg.to8(), cc);
15731573
1574 const scratch_reg = temp_regs[1];1574 const scratch_reg = temp_regs[1];
1575 try self.genSetReg(extended_ty, scratch_reg, .{ .register = reg });1575 try self.genSetReg(extended_ty, scratch_reg, .{ .register = reg });
...@@ -1582,7 +1582,7 @@ fn genSetStackTruncatedOverflowCompare(...@@ -1582,7 +1582,7 @@ fn genSetStackTruncatedOverflowCompare(
1582 );1582 );
15831583
1584 const eq_reg = temp_regs[2];1584 const eq_reg = temp_regs[2];
1585 try self.asmSetCCRegister(eq_reg.to8(), .ne);1585 try self.asmSetccRegister(eq_reg.to8(), .ne);
1586 try self.genBinOpMir(1586 try self.genBinOpMir(
1587 .@"or",1587 .@"or",
1588 Type.u8,1588 Type.u8,
...@@ -1725,26 +1725,10 @@ fn genIntMulDivOpMir(...@@ -1725,26 +1725,10 @@ fn genIntMulDivOpMir(
1725 try self.genSetReg(ty, .rax, lhs);1725 try self.genSetReg(ty, .rax, lhs);
1726 }1726 }
17271727
1728 _ = signedness;1728 switch (signedness) {
1729 // switch (signedness) {1729 .signed => try self.asmNone(.cqo),
1730 // .signed => {1730 .unsigned => try self.asmRegisterRegister(.xor, .rdx, .rdx),
1731 // _ = try self.addInst(.{1731 }
1732 // .tag = .cwd,
1733 // .ops = Mir.Inst.Ops.encode(.{ .flags = 0b11 }),
1734 // .data = undefined,
1735 // });
1736 // },
1737 // .unsigned => {
1738 // _ = try self.addInst(.{
1739 // .tag = .xor,
1740 // .ops = Mir.Inst.Ops.encode(.{
1741 // .reg1 = .rdx,
1742 // .reg2 = .rdx,
1743 // }),
1744 // .data = undefined,
1745 // });
1746 // },
1747 // }
17481732
1749 const factor = switch (rhs) {1733 const factor = switch (rhs) {
1750 .register => rhs,1734 .register => rhs,
...@@ -1754,35 +1738,28 @@ fn genIntMulDivOpMir(...@@ -1754,35 +1738,28 @@ fn genIntMulDivOpMir(
1754 break :blk MCValue{ .register = reg };1738 break :blk MCValue{ .register = reg };
1755 },1739 },
1756 };1740 };
1757 _ = factor;1741
1758 _ = tag;1742 switch (factor) {
17591743 .register => |reg| try self.asmRegister(tag, reg),
1760 // switch (factor) {1744 .stack_offset => |off| {
1761 // .register => |reg| {1745 _ = off;
1762 // _ = try self.addInst(.{1746 // _ = try self.addInst(.{
1763 // .tag = tag,1747 // .tag = tag,
1764 // .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg }),1748 // .ops = Mir.Inst.Ops.encode(.{
1765 // .data = undefined,1749 // .reg2 = .rbp,
1766 // });1750 // .flags = switch (abi_size) {
1767 // },1751 // 1 => 0b00,
1768 // .stack_offset => |off| {1752 // 2 => 0b01,
1769 // _ = try self.addInst(.{1753 // 4 => 0b10,
1770 // .tag = tag,1754 // 8 => 0b11,
1771 // .ops = Mir.Inst.Ops.encode(.{1755 // else => unreachable,
1772 // .reg2 = .rbp,1756 // },
1773 // .flags = switch (abi_size) {1757 // }),
1774 // 1 => 0b00,1758 // .data = .{ .disp = -off },
1775 // 2 => 0b01,1759 // });
1776 // 4 => 0b10,1760 },
1777 // 8 => 0b11,1761 else => unreachable,
1778 // else => unreachable,1762 }
1779 // },
1780 // }),
1781 // .data = .{ .disp = -off },
1782 // });
1783 // },
1784 // else => unreachable,
1785 // }
1786}1763}
17871764
1788/// Always returns a register.1765/// Always returns a register.
...@@ -1808,31 +1785,10 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa...@@ -1808,31 +1785,10 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
1808 .unsigned => .div,1785 .unsigned => .div,
1809 }, Type.isize, signedness, .{ .register = dividend }, .{ .register = divisor });1786 }, Type.isize, signedness, .{ .register = dividend }, .{ .register = divisor });
18101787
1811 // _ = try self.addInst(.{1788 try self.asmRegisterRegister(.xor, divisor.to64(), dividend.to64());
1812 // .tag = .xor,1789 try self.asmRegisterImmediate(.sar, divisor.to64(), Immediate.u(63));
1813 // .ops = Mir.Inst.Ops.encode(.{1790 try self.asmRegisterRegister(.@"test", .rdx, .rdx);
1814 // .reg1 = divisor.to64(),1791 try self.asmCmovccRegisterRegister(divisor.to64(), .rdx, .e);
1815 // .reg2 = dividend.to64(),
1816 // }),
1817 // .data = undefined,
1818 // });
1819 // _ = try self.addInst(.{
1820 // .tag = .sar,
1821 // .ops = Mir.Inst.Ops.encode(.{
1822 // .reg1 = divisor.to64(),
1823 // .flags = 0b10,
1824 // }),
1825 // .data = .{ .imm = 63 },
1826 // });
1827 // _ = try self.addInst(.{
1828 // .tag = .@"test",
1829 // .ops = Mir.Inst.Ops.encode(.{
1830 // .reg1 = .rdx,
1831 // .reg2 = .rdx,
1832 // }),
1833 // .data = undefined,
1834 // });
1835 try self.asmCmovCCRegisterRegister(divisor.to64(), .rdx, .e);
1836 try self.genBinOpMir(.add, Type.isize, .{ .register = divisor }, .{ .register = .rax });1792 try self.genBinOpMir(.add, Type.isize, .{ .register = divisor }, .{ .register = .rax });
1837 return MCValue{ .register = divisor };1793 return MCValue{ .register = divisor };
1838}1794}
...@@ -2877,7 +2833,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2877,7 +2833,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2877 const overflow_bit_ty = value_ty.structFieldType(1);2833 const overflow_bit_ty = value_ty.structFieldType(1);
2878 const overflow_bit_offset = value_ty.structFieldOffset(1, self.target.*);2834 const overflow_bit_offset = value_ty.structFieldOffset(1, self.target.*);
2879 const tmp_reg = try self.register_manager.allocReg(null, gp);2835 const tmp_reg = try self.register_manager.allocReg(null, gp);
2880 try self.asmSetCCRegister(tmp_reg.to8(), ro.eflags);2836 try self.asmSetccRegister(tmp_reg.to8(), ro.eflags);
2881 try self.genInlineMemcpyRegisterRegister(2837 try self.genInlineMemcpyRegisterRegister(
2882 overflow_bit_ty,2838 overflow_bit_ty,
2883 reg,2839 reg,
...@@ -3151,14 +3107,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3151,14 +3107,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3151 };3107 };
3152 const field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*));3108 const field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*));
3153 if (signedness == .signed and field_size < 8) {3109 if (signedness == .signed and field_size < 8) {
3154 // _ = try self.addInst(.{3110 try self.asmRegisterRegister(
3155 // .tag = .mov_sign_extend,3111 .movsx,
3156 // .ops = Mir.Inst.Ops.encode(.{3112 dst_mcv.register,
3157 // .reg1 = dst_mcv.register,3113 registerAlias(dst_mcv.register, field_size),
3158 // .reg2 = registerAlias(dst_mcv.register, field_size),3114 );
3159 // }),
3160 // .data = undefined,
3161 // });
3162 }3115 }
31633116
3164 break :result dst_mcv;3117 break :result dst_mcv;
...@@ -3175,7 +3128,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3175,7 +3128,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3175 defer self.register_manager.unlockReg(reg_lock);3128 defer self.register_manager.unlockReg(reg_lock);
31763129
3177 const dst_reg = try self.register_manager.allocReg(inst, gp);3130 const dst_reg = try self.register_manager.allocReg(inst, gp);
3178 try self.asmSetCCRegister(dst_reg.to8(), ro.eflags);3131 try self.asmSetccRegister(dst_reg.to8(), ro.eflags);
3179 break :result MCValue{ .register = dst_reg.to8() };3132 break :result MCValue{ .register = dst_reg.to8() };
3180 },3133 },
3181 else => unreachable,3134 else => unreachable,
...@@ -3211,25 +3164,7 @@ fn genShiftBinOpMir(self: *Self, tag: Mir.Inst.Tag, ty: Type, reg: Register, shi...@@ -3211,25 +3164,7 @@ fn genShiftBinOpMir(self: *Self, tag: Mir.Inst.Tag, ty: Type, reg: Register, shi
3211 switch (shift) {3164 switch (shift) {
3212 .immediate => |imm| switch (imm) {3165 .immediate => |imm| switch (imm) {
3213 0 => return,3166 0 => return,
3214 1 => {3167 else => return self.asmRegisterImmediate(tag, registerAlias(reg, abi_size), Immediate.u(imm)),
3215 // _ = try self.addInst(.{
3216 // .tag = tag,
3217 // .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(reg, abi_size) }),
3218 // .data = undefined,
3219 // });
3220 return;
3221 },
3222 else => {
3223 // _ = try self.addInst(.{
3224 // .tag = tag,
3225 // .ops = Mir.Inst.Ops.encode(.{
3226 // .reg1 = registerAlias(reg, abi_size),
3227 // .flags = 0b10,
3228 // }),
3229 // .data = .{ .imm = @intCast(u8, imm) },
3230 // });
3231 return;
3232 },
3233 },3168 },
3234 .register => |shift_reg| {3169 .register => |shift_reg| {
3235 if (shift_reg == .rcx) break :blk;3170 if (shift_reg == .rcx) break :blk;
...@@ -3240,16 +3175,8 @@ fn genShiftBinOpMir(self: *Self, tag: Mir.Inst.Tag, ty: Type, reg: Register, shi...@@ -3240,16 +3175,8 @@ fn genShiftBinOpMir(self: *Self, tag: Mir.Inst.Tag, ty: Type, reg: Register, shi
3240 try self.register_manager.getReg(.rcx, null);3175 try self.register_manager.getReg(.rcx, null);
3241 try self.genSetReg(Type.u8, .rcx, shift);3176 try self.genSetReg(Type.u8, .rcx, shift);
3242 }3177 }
3243 _ = abi_size;
32443178
3245 // _ = try self.addInst(.{3179 try self.asmRegisterRegister(tag, registerAlias(reg, abi_size), .cl);
3246 // .tag = tag,
3247 // .ops = Mir.Inst.Ops.encode(.{
3248 // .reg1 = registerAlias(reg, abi_size),
3249 // .flags = 0b01,
3250 // }),
3251 // .data = undefined,
3252 // });
3253}3180}
32543181
3255/// Result is always a register.3182/// Result is always a register.
...@@ -3620,43 +3547,38 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu...@@ -3620,43 +3547,38 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
3620 .register => |src_reg| switch (dst_ty.zigTypeTag()) {3547 .register => |src_reg| switch (dst_ty.zigTypeTag()) {
3621 .Float => {3548 .Float => {
3622 if (intrinsicsAllowed(self.target.*, dst_ty)) {3549 if (intrinsicsAllowed(self.target.*, dst_ty)) {
3623 // const actual_tag: Mir.Inst.Tag = switch (dst_ty.tag()) {3550 const actual_tag: Mir.Inst.Tag = switch (dst_ty.tag()) {
3624 // .f32 => switch (mir_tag) {3551 .f32 => switch (mir_tag) {
3625 // .add => Mir.Inst.Tag.add_f32,3552 .add => .addss,
3626 // .cmp => Mir.Inst.Tag.cmp_f32,3553 .cmp => .cmpss,
3627 // else => return self.fail("TODO genBinOpMir for f32 register-register with MIR tag {}", .{mir_tag}),3554 else => return self.fail(
3628 // },3555 "TODO genBinOpMir for f32 register-register with MIR tag {}",
3629 // .f64 => switch (mir_tag) {3556 .{mir_tag},
3630 // .add => Mir.Inst.Tag.add_f64,3557 ),
3631 // .cmp => Mir.Inst.Tag.cmp_f64,3558 },
3632 // else => return self.fail("TODO genBinOpMir for f64 register-register with MIR tag {}", .{mir_tag}),3559 .f64 => switch (mir_tag) {
3633 // },3560 .add => .addsd,
3634 // else => return self.fail("TODO genBinOpMir for float register-register and type {}", .{dst_ty.fmtDebug()}),3561 .cmp => .cmpsd,
3635 // };3562 else => return self.fail(
3636 // _ = try self.addInst(.{3563 "TODO genBinOpMir for f64 register-register with MIR tag {}",
3637 // .tag = actual_tag,3564 .{mir_tag},
3638 // .ops = Mir.Inst.Ops.encode(.{3565 ),
3639 // .reg1 = dst_reg.to128(),3566 },
3640 // .reg2 = src_reg.to128(),3567 else => return self.fail(
3641 // }),3568 "TODO genBinOpMir for float register-register and type {}",
3642 // .data = undefined,3569 .{dst_ty.fmtDebug()},
3643 // });3570 ),
3644 return;3571 };
3572 try self.asmRegisterRegister(actual_tag, dst_reg.to128(), src_reg.to128());
3645 }3573 }
36463574
3647 return self.fail("TODO genBinOpMir for float register-register and no intrinsics", .{});3575 return self.fail("TODO genBinOpMir for float register-register and no intrinsics", .{});
3648 },3576 },
3649 else => {3577 else => try self.asmRegisterRegister(
3650 _ = src_reg;3578 mir_tag,
3651 // _ = try self.addInst(.{3579 registerAlias(dst_reg, abi_size),
3652 // .tag = mir_tag,3580 registerAlias(src_reg, abi_size),
3653 // .ops = Mir.Inst.Ops.encode(.{3581 ),
3654 // .reg1 = registerAlias(dst_reg, abi_size),
3655 // .reg2 = registerAlias(src_reg, abi_size),
3656 // }),
3657 // .data = undefined,
3658 // });
3659 },
3660 },3582 },
3661 .immediate => |imm| {3583 .immediate => |imm| {
3662 _ = imm;3584 _ = imm;
...@@ -3777,7 +3699,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu...@@ -3777,7 +3699,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
3777/// Does not support byte-size operands.3699/// Does not support byte-size operands.
3778fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void {3700fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void {
3779 const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));3701 const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
3780 _ = abi_size;
3781 switch (dst_mcv) {3702 switch (dst_mcv) {
3782 .none => unreachable,3703 .none => unreachable,
3783 .undef => unreachable,3704 .undef => unreachable,
...@@ -3792,18 +3713,11 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -3792,18 +3713,11 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
3792 .dead, .unreach => unreachable,3713 .dead, .unreach => unreachable,
3793 .ptr_stack_offset => unreachable,3714 .ptr_stack_offset => unreachable,
3794 .register_overflow => unreachable,3715 .register_overflow => unreachable,
3795 .register => |src_reg| {3716 .register => |src_reg| try self.asmRegisterRegister(
3796 _ = src_reg;3717 .imul,
3797 // register, register3718 registerAlias(dst_reg, abi_size),
3798 // _ = try self.addInst(.{3719 registerAlias(src_reg, abi_size),
3799 // .tag = .imul_complex,3720 ),
3800 // .ops = Mir.Inst.Ops.encode(.{
3801 // .reg1 = registerAlias(dst_reg, abi_size),
3802 // .reg2 = registerAlias(src_reg, abi_size),
3803 // }),
3804 // .data = undefined,
3805 // });
3806 },
3807 .immediate => |imm| {3721 .immediate => |imm| {
3808 // TODO take into account the type's ABI size when selecting the register alias3722 // TODO take into account the type's ABI size when selecting the register alias
3809 // register, immediate3723 // register, immediate
...@@ -3992,20 +3906,12 @@ fn genVarDbgInfo(...@@ -3992,20 +3906,12 @@ fn genVarDbgInfo(
3992}3906}
39933907
3994fn airTrap(self: *Self) !void {3908fn airTrap(self: *Self) !void {
3995 // _ = try self.addInst(.{3909 try self.asmNone(.ud2);
3996 // .tag = .ud,
3997 // .ops = Mir.Inst.Ops.encode(.{}),
3998 // .data = undefined,
3999 // });
4000 return self.finishAirBookkeeping();3910 return self.finishAirBookkeeping();
4001}3911}
40023912
4003fn airBreakpoint(self: *Self) !void {3913fn airBreakpoint(self: *Self) !void {
4004 // _ = try self.addInst(.{3914 try self.asmNone(.int3);
4005 // .tag = .interrupt,
4006 // .ops = Mir.Inst.Ops.encode(.{}),
4007 // .data = undefined,
4008 // });
4009 return self.finishAirBookkeeping();3915 return self.finishAirBookkeeping();
4010}3916}
40113917
...@@ -4117,13 +4023,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4117,13 +4023,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4117 if (self.bin_file.cast(link.File.Elf)) |elf_file| {4023 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
4118 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);4024 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
4119 const atom = elf_file.getAtom(atom_index);4025 const atom = elf_file.getAtom(atom_index);
4120 const got_addr = @intCast(i32, atom.getOffsetTableAddress(elf_file));4026 const got_addr = atom.getOffsetTableAddress(elf_file);
4121 _ = got_addr;4027 try self.asmImmediate(.call, Immediate.s(@intCast(i32, got_addr)));
4122 // _ = try self.addInst(.{
4123 // .tag = .call,
4124 // .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }),
4125 // .data = .{ .disp = got_addr },
4126 // });
4127 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {4028 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
4128 const atom_index = try coff_file.getOrCreateAtomForDecl(func.owner_decl);4029 const atom_index = try coff_file.getOrCreateAtomForDecl(func.owner_decl);
4129 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;4030 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
...@@ -4133,14 +4034,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4133,14 +4034,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4133 .sym_index = sym_index,4034 .sym_index = sym_index,
4134 },4035 },
4135 });4036 });
4136 // _ = try self.addInst(.{4037 try self.asmRegister(.call, .rax);
4137 // .tag = .call,
4138 // .ops = Mir.Inst.Ops.encode(.{
4139 // .reg1 = .rax,
4140 // .flags = 0b01,
4141 // }),
4142 // .data = undefined,
4143 // });
4144 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {4038 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4145 const atom_index = try macho_file.getOrCreateAtomForDecl(func.owner_decl);4039 const atom_index = try macho_file.getOrCreateAtomForDecl(func.owner_decl);
4146 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;4040 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
...@@ -4150,14 +4044,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4150,14 +4044,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4150 .sym_index = sym_index,4044 .sym_index = sym_index,
4151 },4045 },
4152 });4046 });
4153 // _ = try self.addInst(.{4047 try self.asmRegister(.call, .rax);
4154 // .tag = .call,
4155 // .ops = Mir.Inst.Ops.encode(.{
4156 // .reg1 = .rax,
4157 // .flags = 0b01,
4158 // }),
4159 // .data = undefined,
4160 // });
4161 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {4048 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
4162 const decl_block_index = try p9.seeDecl(func.owner_decl);4049 const decl_block_index = try p9.seeDecl(func.owner_decl);
4163 const decl_block = p9.getDeclBlock(decl_block_index);4050 const decl_block = p9.getDeclBlock(decl_block_index);
...@@ -4166,12 +4053,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4166,12 +4053,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4166 const got_addr = p9.bases.data;4053 const got_addr = p9.bases.data;
4167 const got_index = decl_block.got_index.?;4054 const got_index = decl_block.got_index.?;
4168 const fn_got_addr = got_addr + got_index * ptr_bytes;4055 const fn_got_addr = got_addr + got_index * ptr_bytes;
4169 _ = fn_got_addr;4056 try self.asmImmediate(.call, Immediate.s(@intCast(i32, fn_got_addr)));
4170 // _ = try self.addInst(.{
4171 // .tag = .call,
4172 // .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }),
4173 // .data = .{ .disp = @intCast(i32, fn_got_addr) },
4174 // });
4175 } else unreachable;4057 } else unreachable;
4176 } else if (func_value.castTag(.extern_fn)) |func_payload| {4058 } else if (func_value.castTag(.extern_fn)) |func_payload| {
4177 const extern_fn = func_payload.data;4059 const extern_fn = func_payload.data;
...@@ -4191,14 +4073,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4191,14 +4073,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4191 .sym_index = sym_index,4073 .sym_index = sym_index,
4192 },4074 },
4193 });4075 });
4194 // _ = try self.addInst(.{4076 try self.asmRegister(.call, .rax);
4195 // .tag = .call,
4196 // .ops = Mir.Inst.Ops.encode(.{
4197 // .reg1 = .rax,
4198 // .flags = 0b01,
4199 // }),
4200 // .data = undefined,
4201 // });
4202 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {4077 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4203 const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));4078 const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
4204 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);4079 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
...@@ -4223,23 +4098,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4223,23 +4098,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4223 assert(ty.zigTypeTag() == .Pointer);4098 assert(ty.zigTypeTag() == .Pointer);
4224 const mcv = try self.resolveInst(callee);4099 const mcv = try self.resolveInst(callee);
4225 try self.genSetReg(Type.initTag(.usize), .rax, mcv);4100 try self.genSetReg(Type.initTag(.usize), .rax, mcv);
4226 // _ = try self.addInst(.{4101 try self.asmRegister(.call, .rax);
4227 // .tag = .call,
4228 // .ops = Mir.Inst.Ops.encode(.{
4229 // .reg1 = .rax,
4230 // .flags = 0b01,
4231 // }),
4232 // .data = undefined,
4233 // });
4234 }4102 }
42354103
4236 if (info.stack_byte_count > 0) {4104 if (info.stack_byte_count > 0) {
4237 // Readjust the stack4105 // Readjust the stack
4238 // _ = try self.addInst(.{4106 try self.asmRegisterImmediate(.add, .rsp, Immediate.u(info.stack_byte_count));
4239 // .tag = .add,
4240 // .ops = Mir.Inst.Ops.encode(.{ .reg1 = .rsp }),
4241 // .data = .{ .imm = info.stack_byte_count },
4242 // });
4243 }4107 }
42444108
4245 const result: MCValue = result: {4109 const result: MCValue = result: {
...@@ -4296,12 +4160,12 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -4296,12 +4160,12 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4296 // TODO when implementing defer, this will need to jump to the appropriate defer expression.4160 // TODO when implementing defer, this will need to jump to the appropriate defer expression.
4297 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction4161 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction
4298 // which is available if the jump is 127 bytes or less forward.4162 // which is available if the jump is 127 bytes or less forward.
4299 // const jmp_reloc = try self.addInst(.{4163 const jmp_reloc = try self.addInst(.{
4300 // .tag = .jmp,4164 .tag = .jmp,
4301 // .ops = Mir.Inst.Ops.encode(.{}),4165 .ops = .inst,
4302 // .data = .{ .inst = undefined },4166 .data = .{ .inst = undefined },
4303 // });4167 });
4304 // try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc);4168 try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc);
4305 return self.finishAir(inst, .dead, .{ un_op, .none, .none });4169 return self.finishAir(inst, .dead, .{ un_op, .none, .none });
4306}4170}
43074171
...@@ -4332,12 +4196,12 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -4332,12 +4196,12 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4332 // TODO when implementing defer, this will need to jump to the appropriate defer expression.4196 // TODO when implementing defer, this will need to jump to the appropriate defer expression.
4333 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction4197 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction
4334 // which is available if the jump is 127 bytes or less forward.4198 // which is available if the jump is 127 bytes or less forward.
4335 // const jmp_reloc = try self.addInst(.{4199 const jmp_reloc = try self.addInst(.{
4336 // .tag = .jmp,4200 .tag = .jmp,
4337 // .ops = Mir.Inst.Ops.encode(.{}),4201 .ops = .inst,
4338 // .data = .{ .inst = undefined },4202 .data = .{ .inst = undefined },
4339 // });4203 });
4340 // try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc);4204 try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc);
4341 return self.finishAir(inst, .dead, .{ un_op, .none, .none });4205 return self.finishAir(inst, .dead, .{ un_op, .none, .none });
4342}4206}
43434207
...@@ -4872,13 +4736,12 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void {...@@ -4872,13 +4736,12 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void {
4872 const loop = self.air.extraData(Air.Block, ty_pl.payload);4736 const loop = self.air.extraData(Air.Block, ty_pl.payload);
4873 const body = self.air.extra[loop.end..][0..loop.data.body_len];4737 const body = self.air.extra[loop.end..][0..loop.data.body_len];
4874 const jmp_target = @intCast(u32, self.mir_instructions.len);4738 const jmp_target = @intCast(u32, self.mir_instructions.len);
4875 _ = jmp_target;
4876 try self.genBody(body);4739 try self.genBody(body);
4877 // _ = try self.addInst(.{4740 _ = try self.addInst(.{
4878 // .tag = .jmp,4741 .tag = .jmp,
4879 // .ops = Mir.Inst.Ops.encode(.{}),4742 .ops = .inst,
4880 // .data = .{ .inst = jmp_target },4743 .data = .{ .inst = jmp_target },
4881 // });4744 });
4882 return self.finishAirBookkeeping();4745 return self.finishAirBookkeeping();
4883}4746}
48844747
...@@ -4923,25 +4786,16 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u...@@ -4923,25 +4786,16 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u
4923 .none => unreachable,4786 .none => unreachable,
4924 .undef => unreachable,4787 .undef => unreachable,
4925 .dead, .unreach => unreachable,4788 .dead, .unreach => unreachable,
4926 .immediate => |imm| {4789 .immediate => |imm| try self.asmRegisterImmediate(
4927 _ = imm;4790 .xor,
4928 // _ = try self.addInst(.{4791 registerAlias(cond_reg, abi_size),
4929 // .tag = .xor,4792 Immediate.u(imm),
4930 // .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(cond_reg, abi_size) }),4793 ),
4931 // .data = .{ .imm = @intCast(u32, imm) },4794 .register => |reg| try self.asmRegisterRegister(
4932 // });4795 .xor,
4933 },4796 registerAlias(cond_reg, abi_size),
4934 .register => |reg| {4797 registerAlias(reg, abi_size),
4935 _ = reg;4798 ),
4936 // _ = try self.addInst(.{
4937 // .tag = .xor,
4938 // .ops = Mir.Inst.Ops.encode(.{
4939 // .reg1 = registerAlias(cond_reg, abi_size),
4940 // .reg2 = registerAlias(reg, abi_size),
4941 // }),
4942 // .data = undefined,
4943 // });
4944 },
4945 .stack_offset => {4799 .stack_offset => {
4946 if (abi_size <= 8) {4800 if (abi_size <= 8) {
4947 const reg = try self.copyToTmpRegister(ty, case);4801 const reg = try self.copyToTmpRegister(ty, case);
...@@ -5223,12 +5077,12 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void {...@@ -5223,12 +5077,12 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void {
5223 // Emit a jump with a relocation. It will be patched up after the block ends.5077 // Emit a jump with a relocation. It will be patched up after the block ends.
5224 try block_data.relocs.ensureUnusedCapacity(self.gpa, 1);5078 try block_data.relocs.ensureUnusedCapacity(self.gpa, 1);
5225 // Leave the jump offset undefined5079 // Leave the jump offset undefined
5226 // const jmp_reloc = try self.addInst(.{5080 const jmp_reloc = try self.addInst(.{
5227 // .tag = .jmp,5081 .tag = .jmp,
5228 // .ops = Mir.Inst.Ops.encode(.{}),5082 .ops = .inst,
5229 // .data = .{ .inst = undefined },5083 .data = .{ .inst = undefined },
5230 // });5084 });
5231 // block_data.relocs.appendAssumeCapacity(jmp_reloc);5085 block_data.relocs.appendAssumeCapacity(jmp_reloc);
5232}5086}
52335087
5234fn airAsm(self: *Self, inst: Air.Inst.Index) !void {5088fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
...@@ -5463,11 +5317,15 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -5463,11 +5317,15 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
5463 switch (ty.zigTypeTag()) {5317 switch (ty.zigTypeTag()) {
5464 .Float => {5318 .Float => {
5465 if (intrinsicsAllowed(self.target.*, ty)) {5319 if (intrinsicsAllowed(self.target.*, ty)) {
5466 // const tag: Mir.Inst.Tag = switch (ty.tag()) {5320 const tag: Mir.Inst.Tag = switch (ty.tag()) {
5467 // .f32 => Mir.Inst.Tag.mov_f32,5321 .f32 => .movss,
5468 // .f64 => Mir.Inst.Tag.mov_f64,5322 .f64 => .movsd,
5469 // else => return self.fail("TODO genSetStackArg for register for type {}", .{ty.fmtDebug()}),5323 else => return self.fail(
5470 // };5324 "TODO genSetStackArg for register for type {}",
5325 .{ty.fmtDebug()},
5326 ),
5327 };
5328 _ = tag;
5471 _ = reg;5329 _ = reg;
5472 // _ = try self.addInst(.{5330 // _ = try self.addInst(.{
5473 // .tag = tag,5331 // .tag = tag,
...@@ -5550,7 +5408,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -5550,7 +5408,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
5550 const overflow_bit_ty = ty.structFieldType(1);5408 const overflow_bit_ty = ty.structFieldType(1);
5551 const overflow_bit_offset = ty.structFieldOffset(1, self.target.*);5409 const overflow_bit_offset = ty.structFieldOffset(1, self.target.*);
5552 const tmp_reg = try self.register_manager.allocReg(null, gp);5410 const tmp_reg = try self.register_manager.allocReg(null, gp);
5553 try self.asmSetCCRegister(tmp_reg.to8(), ro.eflags);5411 try self.asmSetccRegister(tmp_reg.to8(), ro.eflags);
55545412
5555 return self.genSetStack(5413 return self.genSetStack(
5556 overflow_bit_ty,5414 overflow_bit_ty,
...@@ -6039,7 +5897,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -6039,7 +5897,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
6039 }5897 }
6040 },5898 },
6041 .eflags => |cc| {5899 .eflags => |cc| {
6042 return self.asmSetCCRegister(reg.to8(), cc);5900 return self.asmSetccRegister(reg.to8(), cc);
6043 },5901 },
6044 .immediate => |x| {5902 .immediate => |x| {
6045 if (x == 0) {5903 if (x == 0) {
...@@ -6069,63 +5927,38 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -6069,63 +5927,38 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
6069 .Int => switch (ty.intInfo(self.target.*).signedness) {5927 .Int => switch (ty.intInfo(self.target.*).signedness) {
6070 .signed => {5928 .signed => {
6071 if (abi_size <= 4) {5929 if (abi_size <= 4) {
6072 // _ = try self.addInst(.{5930 return self.asmRegisterRegister(
6073 // .tag = .mov_sign_extend,5931 .movsx,
6074 // .ops = Mir.Inst.Ops.encode(.{5932 reg.to64(),
6075 // .reg1 = reg.to64(),5933 registerAlias(src_reg, abi_size),
6076 // .reg2 = registerAlias(src_reg, abi_size),5934 );
6077 // }),
6078 // .data = undefined,
6079 // });
6080 return;
6081 }5935 }
6082 },5936 },
6083 .unsigned => {5937 .unsigned => {
6084 if (abi_size <= 2) {5938 if (abi_size <= 2) {
6085 // _ = try self.addInst(.{5939 return self.asmRegisterRegister(
6086 // .tag = .mov_zero_extend,5940 .movzx,
6087 // .ops = Mir.Inst.Ops.encode(.{5941 reg.to64(),
6088 // .reg1 = reg.to64(),5942 registerAlias(src_reg, abi_size),
6089 // .reg2 = registerAlias(src_reg, abi_size),5943 );
6090 // }),
6091 // .data = undefined,
6092 // });
6093 return;
6094 }5944 }
6095 },5945 },
6096 },5946 },
6097 .Float => {5947 .Float => {
6098 if (intrinsicsAllowed(self.target.*, ty)) {5948 if (intrinsicsAllowed(self.target.*, ty)) {
6099 // const tag: Mir.Inst.Tag = switch (ty.tag()) {5949 const tag: Mir.Inst.Tag = switch (ty.tag()) {
6100 // .f32 => Mir.Inst.Tag.mov_f32,5950 .f32 => .movss,
6101 // .f64 => Mir.Inst.Tag.mov_f64,5951 .f64 => .movsd,
6102 // else => return self.fail("TODO genSetReg from register for {}", .{ty.fmtDebug()}),5952 else => return self.fail("TODO genSetReg from register for {}", .{ty.fmtDebug()}),
6103 // };5953 };
6104 // _ = try self.addInst(.{5954 return self.asmRegisterRegister(tag, reg.to128(), src_reg.to128());
6105 // .tag = tag,
6106 // .ops = Mir.Inst.Ops.encode(.{
6107 // .reg1 = reg.to128(),
6108 // .reg2 = src_reg.to128(),
6109 // .flags = 0b10,
6110 // }),
6111 // .data = undefined,
6112 // });
6113 return;
6114 }5955 }
6115
6116 return self.fail("TODO genSetReg from register for float with no intrinsics", .{});5956 return self.fail("TODO genSetReg from register for float with no intrinsics", .{});
6117 },5957 },
6118 else => {},5958 else => {},
6119 }5959 }
61205960
6121 // _ = try self.addInst(.{5961 try self.asmRegisterRegister(.mov, registerAlias(reg, abi_size), registerAlias(src_reg, abi_size));
6122 // .tag = .mov,
6123 // .ops = Mir.Inst.Ops.encode(.{
6124 // .reg1 = registerAlias(reg, abi_size),
6125 // .reg2 = registerAlias(src_reg, abi_size),
6126 // }),
6127 // .data = undefined,
6128 // });
6129 },5962 },
6130 .linker_load => {5963 .linker_load => {
6131 switch (ty.zigTypeTag()) {5964 switch (ty.zigTypeTag()) {
...@@ -6214,7 +6047,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -6214,7 +6047,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
6214 } else {6047 } else {
6215 // If this is RAX, we can use a direct load.6048 // If this is RAX, we can use a direct load.
6216 // Otherwise, we need to load the address, then indirectly load the value.6049 // Otherwise, we need to load the address, then indirectly load the value.
6217 if (reg.id() == 0) {6050 if (reg.to64() == .rax) {
6218 // movabs rax, ds:moffs646051 // movabs rax, ds:moffs64
6219 // const payload = try self.addExtra(Mir.Imm64.encode(x));6052 // const payload = try self.addExtra(Mir.Imm64.encode(x));
6220 // _ = try self.addInst(.{6053 // _ = try self.addInst(.{
src/arch/x86_64/Emit.zig+108-3
...@@ -87,7 +87,6 @@ pub fn lowerMir(emit: *Emit) InnerError!void {...@@ -87,7 +87,6 @@ pub fn lowerMir(emit: *Emit) InnerError!void {
87 .imul,87 .imul,
88 .int3,88 .int3,
89 .mov,89 .mov,
90 .movsx,
91 .movzx,90 .movzx,
92 .mul,91 .mul,
93 .nop,92 .nop,
...@@ -116,7 +115,11 @@ pub fn lowerMir(emit: *Emit) InnerError!void {...@@ -116,7 +115,11 @@ pub fn lowerMir(emit: *Emit) InnerError!void {
116 .ucomisd,115 .ucomisd,
117 => try emit.mirEncodeGeneric(tag, inst),116 => try emit.mirEncodeGeneric(tag, inst),
118117
119 // Pseudo-instructions118 .call,
119 .jmp,
120 => try emit.mirCallJmp(inst),
121
122 .movsx => try emit.mirMovsx(inst),
120 .cmovcc => try emit.mirCmovcc(inst),123 .cmovcc => try emit.mirCmovcc(inst),
121 .setcc => try emit.mirSetcc(inst),124 .setcc => try emit.mirSetcc(inst),
122 .jcc => try emit.mirJcc(inst),125 .jcc => try emit.mirJcc(inst),
...@@ -209,7 +212,7 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE...@@ -209,7 +212,7 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
209 .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) },212 .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) },
210 };213 };
211 },214 },
212 else => unreachable,215 else => unreachable, // TODO
213 }216 }
214217
215 return emit.encode(mnemonic, .{218 return emit.encode(mnemonic, .{
...@@ -220,6 +223,28 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE...@@ -220,6 +223,28 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
220 });223 });
221}224}
222225
226fn mirMovsx(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
227 const ops = emit.mir.instructions.items(.ops)[inst];
228 const data = emit.mir.instructions.items(.data)[inst];
229
230 var op1: Instruction.Operand = .none;
231 var op2: Instruction.Operand = .none;
232 switch (ops) {
233 .rr => {
234 op1 = .{ .reg = data.rr.r1 };
235 op2 = .{ .reg = data.rr.r2 };
236 },
237 else => unreachable, // TODO
238 }
239
240 const mnemonic: Instruction.Mnemonic = if (op1.bitSize() == 64 and op2.bitSize() == 32) .movsxd else .movsx;
241
242 return emit.encode(mnemonic, .{
243 .op1 = op1,
244 .op2 = op2,
245 });
246}
247
223fn mnemonicFromConditionCode(comptime basename: []const u8, cc: bits.Condition) Instruction.Mnemonic {248fn mnemonicFromConditionCode(comptime basename: []const u8, cc: bits.Condition) Instruction.Mnemonic {
224 inline for (@typeInfo(bits.Condition).Enum.fields) |field| {249 inline for (@typeInfo(bits.Condition).Enum.fields) |field| {
225 if (mem.eql(u8, field.name, @tagName(cc)))250 if (mem.eql(u8, field.name, @tagName(cc)))
...@@ -277,6 +302,86 @@ fn mirJcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -277,6 +302,86 @@ fn mirJcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
277 }302 }
278}303}
279304
305fn mirCallJmp(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
306 const tag = emit.mir.instructions.items(.tag)[inst];
307 const mnemonic: Instruction.Mnemonic = switch (tag) {
308 .call => .call,
309 .jmp => .jmp,
310 else => unreachable,
311 };
312 const ops = emit.mir.instructions.items(.ops)[inst];
313 switch (ops) {
314 .inst => {
315 const target = emit.mir.instructions.items(.data)[inst].inst;
316 const source = emit.code.items.len;
317 try emit.encode(mnemonic, .{
318 .op1 = .{ .imm = Immediate.s(0) },
319 });
320 try emit.relocs.append(emit.bin_file.allocator, .{
321 .source = source,
322 .target = target,
323 .offset = emit.code.items.len - 4,
324 .length = 5,
325 });
326 },
327 .r => {
328 const reg = emit.mir.instructions.items(.data)[inst].r;
329 try emit.encode(mnemonic, .{
330 .op1 = .{ .reg = reg },
331 });
332 },
333 .imm_s => {
334 const imm = emit.mir.instructions.items(.data)[inst].imm_s;
335 try emit.encode(mnemonic, .{
336 .op1 = .{ .imm = Immediate.s(imm) },
337 });
338 },
339 else => unreachable, // TODO
340 }
341}
342
343// fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
344// const tag = emit.mir.instructions.items(.tag)[inst];
345// assert(tag == .call_extern);
346// const relocation = emit.mir.instructions.items(.data)[inst].relocation;
347
348// const offset = blk: {
349// // callq
350// try emit.encode(.call, .{
351// .op1 = .{ .imm = Immediate.s(0) },
352// });
353// break :blk @intCast(u32, emit.code.items.len) - 4;
354// };
355
356// if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
357// // Add relocation to the decl.
358// const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
359// const target = macho_file.getGlobalByIndex(relocation.sym_index);
360// try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
361// .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
362// .target = target,
363// .offset = offset,
364// .addend = 0,
365// .pcrel = true,
366// .length = 2,
367// });
368// } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
369// // Add relocation to the decl.
370// const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
371// const target = coff_file.getGlobalByIndex(relocation.sym_index);
372// try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
373// .type = .direct,
374// .target = target,
375// .offset = offset,
376// .addend = 0,
377// .pcrel = true,
378// .length = 2,
379// });
380// } else {
381// return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{});
382// }
383// }
384
280fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {385fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
281 const payload = emit.mir.instructions.items(.data)[inst].payload;386 const payload = emit.mir.instructions.items(.data)[inst].payload;
282 const save_reg_list = emit.mir.extraData(Mir.SaveRegisterList, payload).data;387 const save_reg_list = emit.mir.extraData(Mir.SaveRegisterList, payload).data;