| ... | @@ -491,6 +491,72 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme | ... | @@ -491,6 +491,72 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme |
| 491 | }); | 491 | }); |
| 492 | } | 492 | } |
| 493 | | 493 | |
| | 494 | fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void { |
| | 495 | const ops: Mir.Inst.Ops = switch (m) { |
| | 496 | .sib => .m_sib, |
| | 497 | .rip => .m_rip, |
| | 498 | else => unreachable, |
| | 499 | }; |
| | 500 | const data: Mir.Inst.Data = switch (ops) { |
| | 501 | .m_sib => .{ .payload = try self.addExtra(Mir.MemorySib.encode(m)) }, |
| | 502 | .m_rip => .{ .payload = try self.addExtra(Mir.MemoryRip.encode(m)) }, |
| | 503 | else => unreachable, |
| | 504 | }; |
| | 505 | _ = try self.addInst(.{ |
| | 506 | .tag = tag, |
| | 507 | .ops = ops, |
| | 508 | .data = data, |
| | 509 | }); |
| | 510 | } |
| | 511 | |
| | 512 | fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) !void { |
| | 513 | const ops: Mir.Inst.Ops = switch (m) { |
| | 514 | .sib => .rm_sib, |
| | 515 | .rip => .rm_rip, |
| | 516 | else => unreachable, |
| | 517 | }; |
| | 518 | const data: Mir.Inst.Data = switch (ops) { |
| | 519 | .rm_sib => .{ .rx = .{ |
| | 520 | .r1 = reg, |
| | 521 | .payload = try self.addExtra(Mir.MemorySib.encode(m)), |
| | 522 | } }, |
| | 523 | .rm_rip => .{ .rx = .{ |
| | 524 | .r1 = reg, |
| | 525 | .payload = try self.addExtra(Mir.MemoryRip.encode(m)), |
| | 526 | } }, |
| | 527 | else => unreachable, |
| | 528 | }; |
| | 529 | _ = try self.addInst(.{ |
| | 530 | .tag = tag, |
| | 531 | .ops = ops, |
| | 532 | .data = data, |
| | 533 | }); |
| | 534 | } |
| | 535 | |
| | 536 | fn asmMemoryRegister(self: *Self, tag: Mir.Inst.Tag, m: Memory, reg: Register) !void { |
| | 537 | const ops: Mir.Inst.Ops = switch (m) { |
| | 538 | .sib => .mr_sib, |
| | 539 | .rip => .mr_rip, |
| | 540 | else => unreachable, |
| | 541 | }; |
| | 542 | const data: Mir.Inst.Data = switch (ops) { |
| | 543 | .mr_sib => .{ .rx = .{ |
| | 544 | .r1 = reg, |
| | 545 | .payload = try self.addExtra(Mir.MemorySib.encode(m)), |
| | 546 | } }, |
| | 547 | .mr_rip => .{ .rx = .{ |
| | 548 | .r1 = reg, |
| | 549 | .payload = try self.addExtra(Mir.MemoryRip.encode(m)), |
| | 550 | } }, |
| | 551 | else => unreachable, |
| | 552 | }; |
| | 553 | _ = try self.addInst(.{ |
| | 554 | .tag = tag, |
| | 555 | .ops = ops, |
| | 556 | .data = data, |
| | 557 | }); |
| | 558 | } |
| | 559 | |
| 494 | fn gen(self: *Self) InnerError!void { | 560 | fn gen(self: *Self) InnerError!void { |
| 495 | const cc = self.fn_type.fnCallingConvention(); | 561 | const cc = self.fn_type.fnCallingConvention(); |
| 496 | if (cc != .Naked) { | 562 | if (cc != .Naked) { |
| ... | @@ -1741,23 +1807,10 @@ fn genIntMulDivOpMir( | ... | @@ -1741,23 +1807,10 @@ fn genIntMulDivOpMir( |
| 1741 | | 1807 | |
| 1742 | switch (factor) { | 1808 | switch (factor) { |
| 1743 | .register => |reg| try self.asmRegister(tag, reg), | 1809 | .register => |reg| try self.asmRegister(tag, reg), |
| 1744 | .stack_offset => |off| { | 1810 | .stack_offset => |off| try self.asmMemory(tag, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 1745 | _ = off; | 1811 | .base = .rbp, |
| 1746 | // _ = try self.addInst(.{ | 1812 | .disp = -off, |
| 1747 | // .tag = tag, | 1813 | })), |
| 1748 | // .ops = Mir.Inst.Ops.encode(.{ | | |
| 1749 | // .reg2 = .rbp, | | |
| 1750 | // .flags = switch (abi_size) { | | |
| 1751 | // 1 => 0b00, | | |
| 1752 | // 2 => 0b01, | | |
| 1753 | // 4 => 0b10, | | |
| 1754 | // 8 => 0b11, | | |
| 1755 | // else => unreachable, | | |
| 1756 | // }, | | |
| 1757 | // }), | | |
| 1758 | // .data = .{ .disp = -off }, | | |
| 1759 | // }); | | |
| 1760 | }, | | |
| 1761 | else => unreachable, | 1814 | else => unreachable, |
| 1762 | } | 1815 | } |
| 1763 | } | 1816 | } |
| ... | @@ -2222,19 +2275,10 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { | ... | @@ -2222,19 +2275,10 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 2222 | | 2275 | |
| 2223 | const addr_reg = try self.register_manager.allocReg(null, gp); | 2276 | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 2224 | switch (slice_mcv) { | 2277 | switch (slice_mcv) { |
| 2225 | .stack_offset => |off| { | 2278 | .stack_offset => |off| try self.asmRegisterMemory(.mov, addr_reg.to64(), Memory.sib(.qword, .{ |
| 2226 | _ = off; | 2279 | .base = .rbp, |
| 2227 | // mov reg, [rbp - 8] | 2280 | .disp = -off, |
| 2228 | // _ = try self.addInst(.{ | 2281 | })), |
| 2229 | // .tag = .mov, | | |
| 2230 | // .ops = Mir.Inst.Ops.encode(.{ | | |
| 2231 | // .reg1 = addr_reg.to64(), | | |
| 2232 | // .reg2 = .rbp, | | |
| 2233 | // .flags = 0b01, | | |
| 2234 | // }), | | |
| 2235 | // .data = .{ .disp = -@intCast(i32, off) }, | | |
| 2236 | // }); | | |
| 2237 | }, | | |
| 2238 | else => return self.fail("TODO implement slice_elem_ptr when slice is {}", .{slice_mcv}), | 2282 | else => return self.fail("TODO implement slice_elem_ptr when slice is {}", .{slice_mcv}), |
| 2239 | } | 2283 | } |
| 2240 | // TODO we could allocate register here, but need to expect addr register and potentially | 2284 | // TODO we could allocate register here, but need to expect addr register and potentially |
| ... | @@ -2309,27 +2353,16 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2309,27 +2353,16 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2309 | array_ty.abiAlignment(self.target.*), | 2353 | array_ty.abiAlignment(self.target.*), |
| 2310 | )); | 2354 | )); |
| 2311 | try self.genSetStack(array_ty, off, array, .{}); | 2355 | try self.genSetStack(array_ty, off, array, .{}); |
| 2312 | // lea reg, [rbp] | 2356 | try self.asmRegisterMemory(.lea, addr_reg.to64(), Memory.sib(.qword, .{ |
| 2313 | // _ = try self.addInst(.{ | 2357 | .base = .rbp, |
| 2314 | // .tag = .lea, | 2358 | .disp = -off, |
| 2315 | // .ops = Mir.Inst.Ops.encode(.{ | 2359 | })); |
| 2316 | // .reg1 = addr_reg.to64(), | | |
| 2317 | // .reg2 = .rbp, | | |
| 2318 | // }), | | |
| 2319 | // .data = .{ .disp = -off }, | | |
| 2320 | // }); | | |
| 2321 | }, | 2360 | }, |
| 2322 | .stack_offset => |off| { | 2361 | .stack_offset => |off| { |
| 2323 | _ = off; | 2362 | try self.asmRegisterMemory(.lea, addr_reg.to64(), Memory.sib(.qword, .{ |
| 2324 | // lea reg, [rbp] | 2363 | .base = .rbp, |
| 2325 | // _ = try self.addInst(.{ | 2364 | .disp = -off, |
| 2326 | // .tag = .lea, | 2365 | })); |
| 2327 | // .ops = Mir.Inst.Ops.encode(.{ | | |
| 2328 | // .reg1 = addr_reg.to64(), | | |
| 2329 | // .reg2 = .rbp, | | |
| 2330 | // }), | | |
| 2331 | // .data = .{ .disp = -off }, | | |
| 2332 | // }); | | |
| 2333 | }, | 2366 | }, |
| 2334 | .memory, .linker_load => { | 2367 | .memory, .linker_load => { |
| 2335 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, array); | 2368 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, array); |
| ... | @@ -2366,7 +2399,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2366,7 +2399,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2366 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); | 2399 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); |
| 2367 | | 2400 | |
| 2368 | const elem_ty = ptr_ty.elemType2(); | 2401 | const elem_ty = ptr_ty.elemType2(); |
| 2369 | const elem_abi_size = elem_ty.abiSize(self.target.*); | 2402 | const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*)); |
| 2370 | const index_ty = self.air.typeOf(bin_op.rhs); | 2403 | const index_ty = self.air.typeOf(bin_op.rhs); |
| 2371 | const index = try self.resolveInst(bin_op.rhs); | 2404 | const index = try self.resolveInst(bin_op.rhs); |
| 2372 | const index_lock: ?RegisterLock = switch (index) { | 2405 | const index_lock: ?RegisterLock = switch (index) { |
| ... | @@ -2386,16 +2419,14 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2386,16 +2419,14 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2386 | if (elem_abi_size > 8) { | 2419 | if (elem_abi_size > 8) { |
| 2387 | return self.fail("TODO copy value with size {} from pointer", .{elem_abi_size}); | 2420 | return self.fail("TODO copy value with size {} from pointer", .{elem_abi_size}); |
| 2388 | } else { | 2421 | } else { |
| 2389 | // mov dst_mcv, [dst_mcv] | 2422 | try self.asmRegisterMemory( |
| 2390 | // _ = try self.addInst(.{ | 2423 | .mov, |
| 2391 | // .tag = .mov, | 2424 | registerAlias(dst_mcv.register, elem_abi_size), |
| 2392 | // .ops = Mir.Inst.Ops.encode(.{ | 2425 | Memory.sib(Memory.PtrSize.fromSize(elem_abi_size), .{ |
| 2393 | // .reg1 = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)), | 2426 | .base = dst_mcv.register, |
| 2394 | // .reg2 = dst_mcv.register, | 2427 | .disp = 0, |
| 2395 | // .flags = 0b01, | 2428 | }), |
| 2396 | // }), | 2429 | ); |
| 2397 | // .data = .{ .disp = 0 }, | | |
| 2398 | // }); | | |
| 2399 | break :result .{ .register = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)) }; | 2430 | break :result .{ .register = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)) }; |
| 2400 | } | 2431 | } |
| 2401 | }; | 2432 | }; |
| ... | @@ -2622,7 +2653,7 @@ fn reuseOperand( | ... | @@ -2622,7 +2653,7 @@ fn reuseOperand( |
| 2622 | | 2653 | |
| 2623 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { | 2654 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { |
| 2624 | const elem_ty = ptr_ty.elemType(); | 2655 | const elem_ty = ptr_ty.elemType(); |
| 2625 | const abi_size = elem_ty.abiSize(self.target.*); | 2656 | const abi_size = @intCast(u32, elem_ty.abiSize(self.target.*)); |
| 2626 | switch (ptr) { | 2657 | switch (ptr) { |
| 2627 | .none => unreachable, | 2658 | .none => unreachable, |
| 2628 | .undef => unreachable, | 2659 | .undef => unreachable, |
| ... | @@ -2649,17 +2680,11 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -2649,17 +2680,11 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2649 | .undef => unreachable, | 2680 | .undef => unreachable, |
| 2650 | .eflags => unreachable, | 2681 | .eflags => unreachable, |
| 2651 | .register => |dst_reg| { | 2682 | .register => |dst_reg| { |
| 2652 | _ = dst_reg; | 2683 | try self.asmRegisterMemory( |
| 2653 | // mov dst_reg, [reg] | 2684 | .mov, |
| 2654 | // _ = try self.addInst(.{ | 2685 | registerAlias(dst_reg, abi_size), |
| 2655 | // .tag = .mov, | 2686 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg, .disp = 0 }), |
| 2656 | // .ops = Mir.Inst.Ops.encode(.{ | 2687 | ); |
| 2657 | // .reg1 = registerAlias(dst_reg, @intCast(u32, abi_size)), | | |
| 2658 | // .reg2 = reg, | | |
| 2659 | // .flags = 0b01, | | |
| 2660 | // }), | | |
| 2661 | // .data = .{ .disp = 0 }, | | |
| 2662 | // }); | | |
| 2663 | }, | 2688 | }, |
| 2664 | .stack_offset => |off| { | 2689 | .stack_offset => |off| { |
| 2665 | if (abi_size <= 8) { | 2690 | if (abi_size <= 8) { |
| ... | @@ -2874,17 +2899,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2874,17 +2899,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2874 | | 2899 | |
| 2875 | try self.loadMemPtrIntoRegister(addr_reg, ptr_ty, ptr); | 2900 | try self.loadMemPtrIntoRegister(addr_reg, ptr_ty, ptr); |
| 2876 | | 2901 | |
| 2877 | // to get the actual address of the value we want to modify we have to go through the GOT | 2902 | // To get the actual address of the value we want to modify we have to go through the GOT |
| 2878 | // mov reg, [reg] | 2903 | try self.asmRegisterMemory(.mov, addr_reg.to64(), Memory.sib(.qword, .{ |
| 2879 | // _ = try self.addInst(.{ | 2904 | .base = addr_reg.to64(), |
| 2880 | // .tag = .mov, | 2905 | .disp = 0, |
| 2881 | // .ops = Mir.Inst.Ops.encode(.{ | 2906 | })); |
| 2882 | // .reg1 = addr_reg.to64(), | | |
| 2883 | // .reg2 = addr_reg.to64(), | | |
| 2884 | // .flags = 0b01, | | |
| 2885 | // }), | | |
| 2886 | // .data = .{ .disp = 0 }, | | |
| 2887 | // }); | | |
| 2888 | | 2907 | |
| 2889 | const new_ptr = MCValue{ .register = addr_reg.to64() }; | 2908 | const new_ptr = MCValue{ .register = addr_reg.to64() }; |
| 2890 | | 2909 | |
| ... | @@ -2936,16 +2955,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2936,16 +2955,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2936 | defer self.register_manager.unlockReg(tmp_reg_lock); | 2955 | defer self.register_manager.unlockReg(tmp_reg_lock); |
| 2937 | | 2956 | |
| 2938 | try self.loadMemPtrIntoRegister(tmp_reg, value_ty, value); | 2957 | try self.loadMemPtrIntoRegister(tmp_reg, value_ty, value); |
| | 2958 | try self.asmRegisterMemory(.mov, tmp_reg, Memory.sib(.qword, .{ |
| | 2959 | .base = tmp_reg, |
| | 2960 | .disp = 0, |
| | 2961 | })); |
| 2939 | | 2962 | |
| 2940 | // _ = try self.addInst(.{ | | |
| 2941 | // .tag = .mov, | | |
| 2942 | // .ops = Mir.Inst.Ops.encode(.{ | | |
| 2943 | // .reg1 = tmp_reg, | | |
| 2944 | // .reg2 = tmp_reg, | | |
| 2945 | // .flags = 0b01, | | |
| 2946 | // }), | | |
| 2947 | // .data = .{ .disp = 0 }, | | |
| 2948 | // }); | | |
| 2949 | return self.store(new_ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); | 2963 | return self.store(new_ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); |
| 2950 | } | 2964 | } |
| 2951 | | 2965 | |
| ... | @@ -3603,15 +3617,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3603,15 +3617,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3603 | if (off > math.maxInt(i32)) { | 3617 | if (off > math.maxInt(i32)) { |
| 3604 | return self.fail("stack offset too large", .{}); | 3618 | return self.fail("stack offset too large", .{}); |
| 3605 | } | 3619 | } |
| 3606 | // _ = try self.addInst(.{ | 3620 | try self.asmRegisterMemory( |
| 3607 | // .tag = mir_tag, | 3621 | mir_tag, |
| 3608 | // .ops = Mir.Inst.Ops.encode(.{ | 3622 | registerAlias(dst_reg, abi_size), |
| 3609 | // .reg1 = registerAlias(dst_reg, abi_size), | 3623 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }), |
| 3610 | // .reg2 = .rbp, | 3624 | ); |
| 3611 | // .flags = 0b01, | | |
| 3612 | // }), | | |
| 3613 | // .data = .{ .disp = -off }, | | |
| 3614 | // }); | | |
| 3615 | }, | 3625 | }, |
| 3616 | } | 3626 | } |
| 3617 | }, | 3627 | }, |
| ... | @@ -3629,16 +3639,10 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3629,16 +3639,10 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3629 | .dead, .unreach => unreachable, | 3639 | .dead, .unreach => unreachable, |
| 3630 | .register_overflow => unreachable, | 3640 | .register_overflow => unreachable, |
| 3631 | .register => |src_reg| { | 3641 | .register => |src_reg| { |
| 3632 | _ = src_reg; | 3642 | try self.asmMemoryRegister(mir_tag, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 3633 | // _ = try self.addInst(.{ | 3643 | .base = .rbp, |
| 3634 | // .tag = mir_tag, | 3644 | .disp = -off, |
| 3635 | // .ops = Mir.Inst.Ops.encode(.{ | 3645 | }), registerAlias(src_reg, abi_size)); |
| 3636 | // .reg1 = .rbp, | | |
| 3637 | // .reg2 = registerAlias(src_reg, abi_size), | | |
| 3638 | // .flags = 0b10, | | |
| 3639 | // }), | | |
| 3640 | // .data = .{ .disp = -off }, | | |
| 3641 | // }); | | |
| 3642 | }, | 3646 | }, |
| 3643 | .immediate => |imm| { | 3647 | .immediate => |imm| { |
| 3644 | _ = imm; | 3648 | _ = imm; |
| ... | @@ -3738,16 +3742,11 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M | ... | @@ -3738,16 +3742,11 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3738 | } | 3742 | } |
| 3739 | }, | 3743 | }, |
| 3740 | .stack_offset => |off| { | 3744 | .stack_offset => |off| { |
| 3741 | _ = off; | 3745 | try self.asmRegisterMemory( |
| 3742 | // _ = try self.addInst(.{ | 3746 | .imul, |
| 3743 | // .tag = .imul_complex, | 3747 | registerAlias(dst_reg, abi_size), |
| 3744 | // .ops = Mir.Inst.Ops.encode(.{ | 3748 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }), |
| 3745 | // .reg1 = registerAlias(dst_reg, abi_size), | 3749 | ); |
| 3746 | // .reg2 = .rbp, | | |
| 3747 | // .flags = 0b01, | | |
| 3748 | // }), | | |
| 3749 | // .data = .{ .disp = -off }, | | |
| 3750 | // }); | | |
| 3751 | }, | 3750 | }, |
| 3752 | .memory => { | 3751 | .memory => { |
| 3753 | return self.fail("TODO implement x86 multiply source memory", .{}); | 3752 | return self.fail("TODO implement x86 multiply source memory", .{}); |
| ... | @@ -3770,17 +3769,11 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M | ... | @@ -3770,17 +3769,11 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3770 | .register => |src_reg| { | 3769 | .register => |src_reg| { |
| 3771 | // copy dst to a register | 3770 | // copy dst to a register |
| 3772 | const dst_reg = try self.copyToTmpRegister(dst_ty, dst_mcv); | 3771 | const dst_reg = try self.copyToTmpRegister(dst_ty, dst_mcv); |
| 3773 | _ = src_reg; | 3772 | try self.asmRegisterRegister( |
| 3774 | // multiply into dst_reg | 3773 | .imul, |
| 3775 | // register, register | 3774 | registerAlias(dst_reg, abi_size), |
| 3776 | // _ = try self.addInst(.{ | 3775 | registerAlias(src_reg, abi_size), |
| 3777 | // .tag = .imul_complex, | 3776 | ); |
| 3778 | // .ops = Mir.Inst.Ops.encode(.{ | | |
| 3779 | // .reg1 = registerAlias(dst_reg, abi_size), | | |
| 3780 | // .reg2 = registerAlias(src_reg, abi_size), | | |
| 3781 | // }), | | |
| 3782 | // .data = undefined, | | |
| 3783 | // }); | | |
| 3784 | // copy dst_reg back out | 3777 | // copy dst_reg back out |
| 3785 | return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{}); | 3778 | return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{}); |
| 3786 | }, | 3779 | }, |
| ... | @@ -4006,11 +3999,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4006,11 +3999,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4006 | | 3999 | |
| 4007 | if (info.stack_byte_count > 0) { | 4000 | if (info.stack_byte_count > 0) { |
| 4008 | // Adjust the stack | 4001 | // Adjust the stack |
| 4009 | // _ = try self.addInst(.{ | 4002 | try self.asmRegisterImmediate(.sub, .rsp, Immediate.u(info.stack_byte_count)); |
| 4010 | // .tag = .sub, | | |
| 4011 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = .rsp }), | | |
| 4012 | // .data = .{ .imm = info.stack_byte_count }, | | |
| 4013 | // }); | | |
| 4014 | } | 4003 | } |
| 4015 | | 4004 | |
| 4016 | // Due to incremental compilation, how function calls are generated depends | 4005 | // Due to incremental compilation, how function calls are generated depends |
| ... | @@ -4161,7 +4150,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4161,7 +4150,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 4161 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction | 4150 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction |
| 4162 | // which is available if the jump is 127 bytes or less forward. | 4151 | // which is available if the jump is 127 bytes or less forward. |
| 4163 | const jmp_reloc = try self.addInst(.{ | 4152 | const jmp_reloc = try self.addInst(.{ |
| 4164 | .tag = .jmp, | 4153 | .tag = .jmp_reloc, |
| 4165 | .ops = .inst, | 4154 | .ops = .inst, |
| 4166 | .data = .{ .inst = undefined }, | 4155 | .data = .{ .inst = undefined }, |
| 4167 | }); | 4156 | }); |
| ... | @@ -4197,7 +4186,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4197,7 +4186,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 4197 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction | 4186 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction |
| 4198 | // which is available if the jump is 127 bytes or less forward. | 4187 | // which is available if the jump is 127 bytes or less forward. |
| 4199 | const jmp_reloc = try self.addInst(.{ | 4188 | const jmp_reloc = try self.addInst(.{ |
| 4200 | .tag = .jmp, | 4189 | .tag = .jmp_reloc, |
| 4201 | .ops = .inst, | 4190 | .ops = .inst, |
| 4202 | .data = .{ .inst = undefined }, | 4191 | .data = .{ .inst = undefined }, |
| 4203 | }); | 4192 | }); |
| ... | @@ -4738,7 +4727,7 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4738,7 +4727,7 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { |
| 4738 | const jmp_target = @intCast(u32, self.mir_instructions.len); | 4727 | const jmp_target = @intCast(u32, self.mir_instructions.len); |
| 4739 | try self.genBody(body); | 4728 | try self.genBody(body); |
| 4740 | _ = try self.addInst(.{ | 4729 | _ = try self.addInst(.{ |
| 4741 | .tag = .jmp, | 4730 | .tag = .jmp_reloc, |
| 4742 | .ops = .inst, | 4731 | .ops = .inst, |
| 4743 | .data = .{ .inst = jmp_target }, | 4732 | .data = .{ .inst = jmp_target }, |
| 4744 | }); | 4733 | }); |
| ... | @@ -5035,7 +5024,7 @@ fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void { | ... | @@ -5035,7 +5024,7 @@ fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void { |
| 5035 | .jcc => { | 5024 | .jcc => { |
| 5036 | self.mir_instructions.items(.data)[reloc].inst_cc.inst = next_inst; | 5025 | self.mir_instructions.items(.data)[reloc].inst_cc.inst = next_inst; |
| 5037 | }, | 5026 | }, |
| 5038 | .jmp => { | 5027 | .jmp_reloc => { |
| 5039 | self.mir_instructions.items(.data)[reloc].inst = next_inst; | 5028 | self.mir_instructions.items(.data)[reloc].inst = next_inst; |
| 5040 | }, | 5029 | }, |
| 5041 | else => unreachable, | 5030 | else => unreachable, |
| ... | @@ -5078,7 +5067,7 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void { | ... | @@ -5078,7 +5067,7 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void { |
| 5078 | try block_data.relocs.ensureUnusedCapacity(self.gpa, 1); | 5067 | try block_data.relocs.ensureUnusedCapacity(self.gpa, 1); |
| 5079 | // Leave the jump offset undefined | 5068 | // Leave the jump offset undefined |
| 5080 | const jmp_reloc = try self.addInst(.{ | 5069 | const jmp_reloc = try self.addInst(.{ |
| 5081 | .tag = .jmp, | 5070 | .tag = .jmp_reloc, |
| 5082 | .ops = .inst, | 5071 | .ops = .inst, |
| 5083 | .data = .{ .inst = undefined }, | 5072 | .data = .{ .inst = undefined }, |
| 5084 | }); | 5073 | }); |
| ... | @@ -5247,7 +5236,7 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { | ... | @@ -5247,7 +5236,7 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { |
| 5247 | } | 5236 | } |
| 5248 | | 5237 | |
| 5249 | fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerError!void { | 5238 | fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerError!void { |
| 5250 | const abi_size = ty.abiSize(self.target.*); | 5239 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 5251 | switch (mcv) { | 5240 | switch (mcv) { |
| 5252 | .dead => unreachable, | 5241 | .dead => unreachable, |
| 5253 | .unreach, .none => return, | 5242 | .unreach, .none => return, |
| ... | @@ -5325,36 +5314,25 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE | ... | @@ -5325,36 +5314,25 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5325 | .{ty.fmtDebug()}, | 5314 | .{ty.fmtDebug()}, |
| 5326 | ), | 5315 | ), |
| 5327 | }; | 5316 | }; |
| 5328 | _ = tag; | 5317 | // TODO verify this |
| 5329 | _ = reg; | 5318 | const ptr_size: Memory.PtrSize = switch (ty.tag()) { |
| 5330 | // _ = try self.addInst(.{ | 5319 | .f32 => .dword, |
| 5331 | // .tag = tag, | 5320 | .f64 => .qword, |
| 5332 | // .ops = Mir.Inst.Ops.encode(.{ | 5321 | else => unreachable, |
| 5333 | // .reg1 = switch (ty.tag()) { | 5322 | }; |
| 5334 | // .f32 => .esp, | 5323 | return self.asmMemoryRegister(tag, Memory.sib(ptr_size, .{ |
| 5335 | // .f64 => .rsp, | 5324 | .base = .rsp, |
| 5336 | // else => unreachable, | 5325 | .disp = -stack_offset, |
| 5337 | // }, | 5326 | }), reg.to128()); |
| 5338 | // .reg2 = reg.to128(), | | |
| 5339 | // .flags = 0b01, | | |
| 5340 | // }), | | |
| 5341 | // .data = .{ .disp = -stack_offset }, | | |
| 5342 | // }); | | |
| 5343 | return; | | |
| 5344 | } | 5327 | } |
| 5345 | | 5328 | |
| 5346 | return self.fail("TODO genSetStackArg for register with no intrinsics", .{}); | 5329 | return self.fail("TODO genSetStackArg for register with no intrinsics", .{}); |
| 5347 | }, | 5330 | }, |
| 5348 | else => { | 5331 | else => { |
| 5349 | // _ = try self.addInst(.{ | 5332 | try self.asmMemoryRegister(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 5350 | // .tag = .mov, | 5333 | .base = .rsp, |
| 5351 | // .ops = Mir.Inst.Ops.encode(.{ | 5334 | .disp = -stack_offset, |
| 5352 | // .reg1 = .rsp, | 5335 | }), registerAlias(reg, abi_size)); |
| 5353 | // .reg2 = registerAlias(reg, @intCast(u32, abi_size)), | | |
| 5354 | // .flags = 0b10, | | |
| 5355 | // }), | | |
| 5356 | // .data = .{ .disp = -stack_offset }, | | |
| 5357 | // }); | | |
| 5358 | }, | 5336 | }, |
| 5359 | } | 5337 | } |
| 5360 | }, | 5338 | }, |
| ... | @@ -5507,25 +5485,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl | ... | @@ -5507,25 +5485,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5507 | switch (ty.zigTypeTag()) { | 5485 | switch (ty.zigTypeTag()) { |
| 5508 | .Float => { | 5486 | .Float => { |
| 5509 | if (intrinsicsAllowed(self.target.*, ty)) { | 5487 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 5510 | // const tag: Mir.Inst.Tag = switch (ty.tag()) { | 5488 | const tag: Mir.Inst.Tag = switch (ty.tag()) { |
| 5511 | // .f32 => Mir.Inst.Tag.mov_f32, | 5489 | .f32 => .movss, |
| 5512 | // .f64 => Mir.Inst.Tag.mov_f64, | 5490 | .f64 => .movsd, |
| 5513 | // else => return self.fail("TODO genSetStack for register for type {}", .{ty.fmtDebug()}), | 5491 | else => return self.fail( |
| 5514 | // }; | 5492 | "TODO genSetStack for register for type {}", |
| 5515 | // _ = try self.addInst(.{ | 5493 | .{ty.fmtDebug()}, |
| 5516 | // .tag = tag, | 5494 | ), |
| 5517 | // .ops = Mir.Inst.Ops.encode(.{ | 5495 | }; |
| 5518 | // .reg1 = switch (ty.tag()) { | 5496 | const ptr_size: Memory.PtrSize = switch (ty.tag()) { |
| 5519 | // .f32 => base_reg.to32(), | 5497 | .f32 => .dword, |
| 5520 | // .f64 => base_reg.to64(), | 5498 | .f64 => .qword, |
| 5521 | // else => unreachable, | 5499 | else => unreachable, |
| 5522 | // }, | 5500 | }; |
| 5523 | // .reg2 = reg.to128(), | 5501 | return self.asmMemoryRegister(tag, Memory.sib(ptr_size, .{ |
| 5524 | // .flags = 0b01, | 5502 | .base = base_reg.to64(), |
| 5525 | // }), | 5503 | .disp = -stack_offset, |
| 5526 | // .data = .{ .disp = -stack_offset }, | 5504 | }), reg.to128()); |
| 5527 | // }); | | |
| 5528 | return; | | |
| 5529 | } | 5505 | } |
| 5530 | | 5506 | |
| 5531 | return self.fail("TODO genSetStack for register for type float with no intrinsics", .{}); | 5507 | return self.fail("TODO genSetStack for register for type float with no intrinsics", .{}); |
| ... | @@ -5590,16 +5566,10 @@ fn genInlineMemcpyRegisterRegister( | ... | @@ -5590,16 +5566,10 @@ fn genInlineMemcpyRegisterRegister( |
| 5590 | var remainder = abi_size; | 5566 | var remainder = abi_size; |
| 5591 | while (remainder > 0) { | 5567 | while (remainder > 0) { |
| 5592 | const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder)); | 5568 | const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder)); |
| 5593 | | 5569 | try self.asmMemoryRegister(.mov, Memory.sib(Memory.PtrSize.fromSize(nearest_power_of_two), .{ |
| 5594 | // _ = try self.addInst(.{ | 5570 | .base = dst_reg, |
| 5595 | // .tag = .mov, | 5571 | .disp = -next_offset, |
| 5596 | // .ops = Mir.Inst.Ops.encode(.{ | 5572 | }), registerAlias(tmp_reg, nearest_power_of_two)); |
| 5597 | // .reg1 = dst_reg, | | |
| 5598 | // .reg2 = registerAlias(tmp_reg, nearest_power_of_two), | | |
| 5599 | // .flags = 0b10, | | |
| 5600 | // }), | | |
| 5601 | // .data = .{ .disp = -next_offset }, | | |
| 5602 | // }); | | |
| 5603 | | 5573 | |
| 5604 | if (nearest_power_of_two > 1) { | 5574 | if (nearest_power_of_two > 1) { |
| 5605 | try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{ | 5575 | try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{ |
| ... | @@ -5611,15 +5581,10 @@ fn genInlineMemcpyRegisterRegister( | ... | @@ -5611,15 +5581,10 @@ fn genInlineMemcpyRegisterRegister( |
| 5611 | next_offset -= nearest_power_of_two; | 5581 | next_offset -= nearest_power_of_two; |
| 5612 | } | 5582 | } |
| 5613 | } else { | 5583 | } else { |
| 5614 | // _ = try self.addInst(.{ | 5584 | try self.asmMemoryRegister(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 5615 | // .tag = .mov, | 5585 | .base = dst_reg, |
| 5616 | // .ops = Mir.Inst.Ops.encode(.{ | 5586 | .disp = -offset, |
| 5617 | // .reg1 = dst_reg, | 5587 | }), registerAlias(src_reg, abi_size)); |
| 5618 | // .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)), | | |
| 5619 | // .flags = 0b10, | | |
| 5620 | // }), | | |
| 5621 | // .data = .{ .disp = -offset }, | | |
| 5622 | // }); | | |
| 5623 | } | 5588 | } |
| 5624 | } | 5589 | } |
| 5625 | | 5590 | |
| ... | @@ -5660,15 +5625,10 @@ fn genInlineMemcpy( | ... | @@ -5660,15 +5625,10 @@ fn genInlineMemcpy( |
| 5660 | try self.loadMemPtrIntoRegister(dst_addr_reg, Type.usize, dst_ptr); | 5625 | try self.loadMemPtrIntoRegister(dst_addr_reg, Type.usize, dst_ptr); |
| 5661 | }, | 5626 | }, |
| 5662 | .ptr_stack_offset, .stack_offset => |off| { | 5627 | .ptr_stack_offset, .stack_offset => |off| { |
| 5663 | _ = off; | 5628 | try self.asmRegisterMemory(.lea, dst_addr_reg.to64(), Memory.sib(.qword, .{ |
| 5664 | // _ = try self.addInst(.{ | 5629 | .base = opts.dest_stack_base orelse .rbp, |
| 5665 | // .tag = .lea, | 5630 | .disp = -off, |
| 5666 | // .ops = Mir.Inst.Ops.encode(.{ | 5631 | })); |
| 5667 | // .reg1 = dst_addr_reg.to64(), | | |
| 5668 | // .reg2 = opts.dest_stack_base orelse .rbp, | | |
| 5669 | // }), | | |
| 5670 | // .data = .{ .disp = -off }, | | |
| 5671 | // }); | | |
| 5672 | }, | 5632 | }, |
| 5673 | .register => |reg| { | 5633 | .register => |reg| { |
| 5674 | try self.asmRegisterRegister( | 5634 | try self.asmRegisterRegister( |
| ... | @@ -5754,7 +5714,7 @@ fn genInlineMemcpy( | ... | @@ -5754,7 +5714,7 @@ fn genInlineMemcpy( |
| 5754 | try self.asmRegisterImmediate(.sub, count_reg, Immediate.u(1)); | 5714 | try self.asmRegisterImmediate(.sub, count_reg, Immediate.u(1)); |
| 5755 | | 5715 | |
| 5756 | _ = try self.addInst(.{ | 5716 | _ = try self.addInst(.{ |
| 5757 | .tag = .jmp, | 5717 | .tag = .jmp_reloc, |
| 5758 | .ops = .inst, | 5718 | .ops = .inst, |
| 5759 | .data = .{ .inst = loop_start }, | 5719 | .data = .{ .inst = loop_start }, |
| 5760 | }); | 5720 | }); |
| ... | @@ -5857,7 +5817,7 @@ fn genInlineMemset( | ... | @@ -5857,7 +5817,7 @@ fn genInlineMemset( |
| 5857 | try self.asmRegisterImmediate(.sub, index_reg, Immediate.u(1)); | 5817 | try self.asmRegisterImmediate(.sub, index_reg, Immediate.u(1)); |
| 5858 | | 5818 | |
| 5859 | _ = try self.addInst(.{ | 5819 | _ = try self.addInst(.{ |
| 5860 | .tag = .jmp, | 5820 | .tag = .jmp_reloc, |
| 5861 | .ops = .inst, | 5821 | .ops = .inst, |
| 5862 | .data = .{ .inst = loop_start }, | 5822 | .data = .{ .inst = loop_start }, |
| 5863 | }); | 5823 | }); |
| ... | @@ -6045,19 +6005,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -6045,19 +6005,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6045 | // .data = .{ .disp = @intCast(i32, x) }, | 6005 | // .data = .{ .disp = @intCast(i32, x) }, |
| 6046 | // }); | 6006 | // }); |
| 6047 | } else { | 6007 | } else { |
| 6048 | // If this is RAX, we can use a direct load. | | |
| 6049 | // Otherwise, we need to load the address, then indirectly load the value. | | |
| 6050 | if (reg.to64() == .rax) { | 6008 | if (reg.to64() == .rax) { |
| 6051 | // movabs rax, ds:moffs64 | 6009 | // If this is RAX, we can use a direct load. |
| 6052 | // const payload = try self.addExtra(Mir.Imm64.encode(x)); | 6010 | // Otherwise, we need to load the address, then indirectly load the value. |
| 6053 | // _ = try self.addInst(.{ | 6011 | var moffs: Mir.MemoryMoffs = .{ |
| 6054 | // .tag = .movabs, | 6012 | .seg = @enumToInt(Register.ds), |
| 6055 | // .ops = Mir.Inst.Ops.encode(.{ | 6013 | .msb = undefined, |
| 6056 | // .reg1 = .rax, | 6014 | .lsb = undefined, |
| 6057 | // .flags = 0b01, // imm64 will become moffs64 | 6015 | }; |
| 6058 | // }), | 6016 | moffs.encodeOffset(x); |
| 6059 | // .data = .{ .payload = payload }, | 6017 | _ = try self.addInst(.{ |
| 6060 | // }); | 6018 | .tag = .mov_moffs, |
| | 6019 | .ops = .rax_moffs, |
| | 6020 | .data = .{ .payload = try self.addExtra(moffs) }, |
| | 6021 | }); |
| 6061 | } else { | 6022 | } else { |
| 6062 | // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue. | 6023 | // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue. |
| 6063 | try self.genSetReg(ty, reg, MCValue{ .immediate = x }); | 6024 | try self.genSetReg(ty, reg, MCValue{ .immediate = x }); |