| ... | ... | @@ -22,8 +22,6 @@ const Liveness = @import("../../Liveness.zig"); |
| 22 | 22 | const Mir = @import("Mir.zig"); |
| 23 | 23 | const Module = @import("../../Module.zig"); |
| 24 | 24 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; |
| 25 | | const RegisterManager = RegisterManagerFn(Self, Register, &allocatable_registers); |
| 26 | | const RegisterLock = RegisterManager.RegisterLock; |
| 27 | 25 | const Target = std.Target; |
| 28 | 26 | const Type = @import("../../type.zig").Type; |
| 29 | 27 | const TypedValue = @import("../../TypedValue.zig"); |
| ... | ... | @@ -31,12 +29,19 @@ const Value = @import("../../value.zig").Value; |
| 31 | 29 | |
| 32 | 30 | const bits = @import("bits.zig"); |
| 33 | 31 | const abi = @import("abi.zig"); |
| 34 | | const Register = bits.Register; |
| 32 | |
| 35 | 33 | const callee_preserved_regs = abi.callee_preserved_regs; |
| 36 | 34 | const caller_preserved_regs = abi.caller_preserved_regs; |
| 37 | 35 | const allocatable_registers = abi.allocatable_registers; |
| 38 | 36 | const c_abi_int_param_regs = abi.c_abi_int_param_regs; |
| 39 | 37 | const c_abi_int_return_regs = abi.c_abi_int_return_regs; |
| 38 | const RegisterManager = RegisterManagerFn(Self, Register, &allocatable_registers, spillInstruction); |
| 39 | const RegisterLock = RegisterManager.RegisterLock; |
| 40 | const Register = bits.Register; |
| 41 | |
| 42 | const AvxRegisterManager = RegisterManagerFn(Self, AvxRegister, &abi.avx_regs, spillInstructionAvx); |
| 43 | const AvxRegisterLock = AvxRegisterManager.RegisterLock; |
| 44 | const AvxRegister = bits.AvxRegister; |
| 40 | 45 | |
| 41 | 46 | const InnerError = error{ |
| 42 | 47 | OutOfMemory, |
| ... | ... | @@ -87,7 +92,8 @@ branch_stack: *std.ArrayList(Branch), |
| 87 | 92 | // Key is the block instruction |
| 88 | 93 | blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, BlockData) = .{}, |
| 89 | 94 | |
| 90 | | register_manager: RegisterManager = .{}, |
| 95 | register_manager: RegisterManager, |
| 96 | avx_register_manager: AvxRegisterManager, |
| 91 | 97 | /// Maps offset to what is stored there. |
| 92 | 98 | stack: std.AutoHashMapUnmanaged(u32, StackAllocation) = .{}, |
| 93 | 99 | |
| ... | ... | @@ -119,14 +125,16 @@ pub const MCValue = union(enum) { |
| 119 | 125 | /// A pointer-sized integer that fits in a register. |
| 120 | 126 | /// If the type is a pointer, this is the pointer address in virtual address space. |
| 121 | 127 | immediate: u64, |
| 122 | | /// The value is in a target-specific register. |
| 128 | /// The value is in a GP register. |
| 123 | 129 | register: Register, |
| 124 | | /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the register, |
| 130 | /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register, |
| 125 | 131 | /// and the operation is an unsigned operation. |
| 126 | 132 | register_overflow_unsigned: Register, |
| 127 | | /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the register, |
| 133 | /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register, |
| 128 | 134 | /// and the operation is a signed operation. |
| 129 | 135 | register_overflow_signed: Register, |
| 136 | /// The value is in an AVX register. |
| 137 | avx_register: AvxRegister, |
| 130 | 138 | /// The value is in memory at a hard-coded address. |
| 131 | 139 | /// If the type is a pointer, it means the pointer address is at this memory location. |
| 132 | 140 | memory: u64, |
| ... | ... | @@ -295,7 +303,11 @@ pub fn generate( |
| 295 | 303 | .mir_to_air_map = if (builtin.mode == .Debug) |
| 296 | 304 | std.AutoHashMap(Mir.Inst.Index, Air.Inst.Index).init(bin_file.allocator) |
| 297 | 305 | else {}, |
| 306 | .register_manager = undefined, |
| 307 | .avx_register_manager = undefined, |
| 298 | 308 | }; |
| 309 | function.register_manager = .{ .function = &function }; |
| 310 | function.avx_register_manager = .{ .function = &function }; |
| 299 | 311 | defer function.stack.deinit(bin_file.allocator); |
| 300 | 312 | defer function.blocks.deinit(bin_file.allocator); |
| 301 | 313 | defer function.exitlude_jump_relocs.deinit(bin_file.allocator); |
| ... | ... | @@ -387,14 +399,14 @@ fn gen(self: *Self) InnerError!void { |
| 387 | 399 | if (cc != .Naked) { |
| 388 | 400 | _ = try self.addInst(.{ |
| 389 | 401 | .tag = .push, |
| 390 | | .ops = (Mir.Ops{ |
| 402 | .ops = (Mir.Ops(Register, Register){ |
| 391 | 403 | .reg1 = .rbp, |
| 392 | 404 | }).encode(), |
| 393 | 405 | .data = undefined, // unused for push reg, |
| 394 | 406 | }); |
| 395 | 407 | _ = try self.addInst(.{ |
| 396 | 408 | .tag = .mov, |
| 397 | | .ops = (Mir.Ops{ |
| 409 | .ops = (Mir.Ops(Register, Register){ |
| 398 | 410 | .reg1 = .rbp, |
| 399 | 411 | .reg2 = .rsp, |
| 400 | 412 | }).encode(), |
| ... | ... | @@ -434,7 +446,7 @@ fn gen(self: *Self) InnerError!void { |
| 434 | 446 | // push the callee_preserved_regs that were used |
| 435 | 447 | const backpatch_push_callee_preserved_regs_i = try self.addInst(.{ |
| 436 | 448 | .tag = .push_regs_from_callee_preserved_regs, |
| 437 | | .ops = (Mir.Ops{ |
| 449 | .ops = (Mir.Ops(Register, Register){ |
| 438 | 450 | .reg1 = .rbp, |
| 439 | 451 | }).encode(), |
| 440 | 452 | .data = .{ .payload = undefined }, // to be backpatched |
| ... | ... | @@ -476,7 +488,7 @@ fn gen(self: *Self) InnerError!void { |
| 476 | 488 | // pop the callee_preserved_regs |
| 477 | 489 | _ = try self.addInst(.{ |
| 478 | 490 | .tag = .pop_regs_from_callee_preserved_regs, |
| 479 | | .ops = (Mir.Ops{ |
| 491 | .ops = (Mir.Ops(Register, Register){ |
| 480 | 492 | .reg1 = .rbp, |
| 481 | 493 | }).encode(), |
| 482 | 494 | .data = .{ .payload = callee_preserved_regs_payload }, |
| ... | ... | @@ -497,7 +509,7 @@ fn gen(self: *Self) InnerError!void { |
| 497 | 509 | |
| 498 | 510 | _ = try self.addInst(.{ |
| 499 | 511 | .tag = .pop, |
| 500 | | .ops = (Mir.Ops{ |
| 512 | .ops = (Mir.Ops(Register, Register){ |
| 501 | 513 | .reg1 = .rbp, |
| 502 | 514 | }).encode(), |
| 503 | 515 | .data = undefined, |
| ... | ... | @@ -505,7 +517,7 @@ fn gen(self: *Self) InnerError!void { |
| 505 | 517 | |
| 506 | 518 | _ = try self.addInst(.{ |
| 507 | 519 | .tag = .ret, |
| 508 | | .ops = (Mir.Ops{ |
| 520 | .ops = (Mir.Ops(Register, Register){ |
| 509 | 521 | .flags = 0b11, |
| 510 | 522 | }).encode(), |
| 511 | 523 | .data = undefined, |
| ... | ... | @@ -521,14 +533,14 @@ fn gen(self: *Self) InnerError!void { |
| 521 | 533 | if (aligned_stack_end > 0) { |
| 522 | 534 | self.mir_instructions.set(backpatch_stack_sub, .{ |
| 523 | 535 | .tag = .sub, |
| 524 | | .ops = (Mir.Ops{ |
| 536 | .ops = (Mir.Ops(Register, Register){ |
| 525 | 537 | .reg1 = .rsp, |
| 526 | 538 | }).encode(), |
| 527 | 539 | .data = .{ .imm = aligned_stack_end }, |
| 528 | 540 | }); |
| 529 | 541 | self.mir_instructions.set(backpatch_stack_add, .{ |
| 530 | 542 | .tag = .add, |
| 531 | | .ops = (Mir.Ops{ |
| 543 | .ops = (Mir.Ops(Register, Register){ |
| 532 | 544 | .reg1 = .rsp, |
| 533 | 545 | }).encode(), |
| 534 | 546 | .data = .{ .imm = aligned_stack_end }, |
| ... | ... | @@ -889,13 +901,27 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 889 | 901 | self.stack_align = abi_align; |
| 890 | 902 | |
| 891 | 903 | if (reg_ok) { |
| 892 | | // Make sure the type can fit in a register before we try to allocate one. |
| 893 | | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 894 | | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 895 | | if (abi_size <= ptr_bytes) { |
| 896 | | if (self.register_manager.tryAllocReg(inst)) |reg| { |
| 897 | | return MCValue{ .register = registerAlias(reg, abi_size) }; |
| 898 | | } |
| 904 | switch (elem_ty.zigTypeTag()) { |
| 905 | .Vector => return self.fail("TODO allocRegOrMem for Vector type", .{}), |
| 906 | .Float => { |
| 907 | // TODO check if AVX available |
| 908 | const ptr_bytes: u64 = 32; |
| 909 | if (abi_size <= ptr_bytes) { |
| 910 | if (self.avx_register_manager.tryAllocReg(inst)) |reg| { |
| 911 | return MCValue{ .avx_register = avxRegisterAlias(reg, abi_size) }; |
| 912 | } |
| 913 | } |
| 914 | }, |
| 915 | else => { |
| 916 | // Make sure the type can fit in a register before we try to allocate one. |
| 917 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 918 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 919 | if (abi_size <= ptr_bytes) { |
| 920 | if (self.register_manager.tryAllocReg(inst)) |reg| { |
| 921 | return MCValue{ .register = registerAlias(reg, abi_size) }; |
| 922 | } |
| 923 | } |
| 924 | }, |
| 899 | 925 | } |
| 900 | 926 | } |
| 901 | 927 | const stack_offset = try self.allocMem(inst, abi_size, abi_align); |
| ... | ... | @@ -920,6 +946,21 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void |
| 920 | 946 | try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv, .{}); |
| 921 | 947 | } |
| 922 | 948 | |
| 949 | pub fn spillInstructionAvx(self: *Self, reg: AvxRegister, inst: Air.Inst.Index) !void { |
| 950 | const stack_mcv = try self.allocRegOrMem(inst, false); |
| 951 | log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv }); |
| 952 | const reg_mcv = self.getResolvedInstValue(inst); |
| 953 | switch (reg_mcv) { |
| 954 | .avx_register => |other| { |
| 955 | assert(reg.to256() == other.to256()); |
| 956 | }, |
| 957 | else => {}, |
| 958 | } |
| 959 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 960 | try branch.inst_table.put(self.gpa, inst, stack_mcv); |
| 961 | try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv, .{}); |
| 962 | } |
| 963 | |
| 923 | 964 | pub fn spillCompareFlagsIfOccupied(self: *Self) !void { |
| 924 | 965 | if (self.compare_flags_inst) |inst_to_save| { |
| 925 | 966 | const mcv = self.getResolvedInstValue(inst_to_save); |
| ... | ... | @@ -1192,7 +1233,7 @@ fn airMin(self: *Self, inst: Air.Inst.Index) !void { |
| 1192 | 1233 | const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, rhs_mcv); |
| 1193 | 1234 | _ = try self.addInst(.{ |
| 1194 | 1235 | .tag = if (signedness == .signed) .cond_mov_lt else .cond_mov_below, |
| 1195 | | .ops = (Mir.Ops{ |
| 1236 | .ops = (Mir.Ops(Register, Register){ |
| 1196 | 1237 | .reg1 = dst_mcv.register, |
| 1197 | 1238 | .reg2 = lhs_reg, |
| 1198 | 1239 | }).encode(), |
| ... | ... | @@ -1396,7 +1437,7 @@ fn genSetStackTruncatedOverflowCompare( |
| 1396 | 1437 | }; |
| 1397 | 1438 | _ = try self.addInst(.{ |
| 1398 | 1439 | .tag = .cond_set_byte_overflow, |
| 1399 | | .ops = (Mir.Ops{ |
| 1440 | .ops = (Mir.Ops(Register, Register){ |
| 1400 | 1441 | .reg1 = overflow_reg.to8(), |
| 1401 | 1442 | .flags = flags, |
| 1402 | 1443 | }).encode(), |
| ... | ... | @@ -1416,7 +1457,7 @@ fn genSetStackTruncatedOverflowCompare( |
| 1416 | 1457 | const eq_reg = temp_regs[2]; |
| 1417 | 1458 | _ = try self.addInst(.{ |
| 1418 | 1459 | .tag = .cond_set_byte_eq_ne, |
| 1419 | | .ops = (Mir.Ops{ |
| 1460 | .ops = (Mir.Ops(Register, Register){ |
| 1420 | 1461 | .reg1 = eq_reg.to8(), |
| 1421 | 1462 | .flags = 0b00, |
| 1422 | 1463 | }).encode(), |
| ... | ... | @@ -1565,7 +1606,7 @@ fn genIntMulDivOpMir( |
| 1565 | 1606 | .signed => { |
| 1566 | 1607 | _ = try self.addInst(.{ |
| 1567 | 1608 | .tag = .cwd, |
| 1568 | | .ops = (Mir.Ops{ |
| 1609 | .ops = (Mir.Ops(Register, Register){ |
| 1569 | 1610 | .flags = 0b11, |
| 1570 | 1611 | }).encode(), |
| 1571 | 1612 | .data = undefined, |
| ... | ... | @@ -1574,7 +1615,7 @@ fn genIntMulDivOpMir( |
| 1574 | 1615 | .unsigned => { |
| 1575 | 1616 | _ = try self.addInst(.{ |
| 1576 | 1617 | .tag = .xor, |
| 1577 | | .ops = (Mir.Ops{ |
| 1618 | .ops = (Mir.Ops(Register, Register){ |
| 1578 | 1619 | .reg1 = .rdx, |
| 1579 | 1620 | .reg2 = .rdx, |
| 1580 | 1621 | }).encode(), |
| ... | ... | @@ -1596,7 +1637,7 @@ fn genIntMulDivOpMir( |
| 1596 | 1637 | .register => |reg| { |
| 1597 | 1638 | _ = try self.addInst(.{ |
| 1598 | 1639 | .tag = tag, |
| 1599 | | .ops = (Mir.Ops{ |
| 1640 | .ops = (Mir.Ops(Register, Register){ |
| 1600 | 1641 | .reg1 = reg, |
| 1601 | 1642 | }).encode(), |
| 1602 | 1643 | .data = undefined, |
| ... | ... | @@ -1605,7 +1646,7 @@ fn genIntMulDivOpMir( |
| 1605 | 1646 | .stack_offset => |off| { |
| 1606 | 1647 | _ = try self.addInst(.{ |
| 1607 | 1648 | .tag = tag, |
| 1608 | | .ops = (Mir.Ops{ |
| 1649 | .ops = (Mir.Ops(Register, Register){ |
| 1609 | 1650 | .reg2 = .rbp, |
| 1610 | 1651 | .flags = switch (abi_size) { |
| 1611 | 1652 | 1 => 0b00, |
| ... | ... | @@ -1647,7 +1688,7 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa |
| 1647 | 1688 | |
| 1648 | 1689 | _ = try self.addInst(.{ |
| 1649 | 1690 | .tag = .xor, |
| 1650 | | .ops = (Mir.Ops{ |
| 1691 | .ops = (Mir.Ops(Register, Register){ |
| 1651 | 1692 | .reg1 = divisor.to64(), |
| 1652 | 1693 | .reg2 = dividend.to64(), |
| 1653 | 1694 | }).encode(), |
| ... | ... | @@ -1655,7 +1696,7 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa |
| 1655 | 1696 | }); |
| 1656 | 1697 | _ = try self.addInst(.{ |
| 1657 | 1698 | .tag = .sar, |
| 1658 | | .ops = (Mir.Ops{ |
| 1699 | .ops = (Mir.Ops(Register, Register){ |
| 1659 | 1700 | .reg1 = divisor.to64(), |
| 1660 | 1701 | .flags = 0b10, |
| 1661 | 1702 | }).encode(), |
| ... | ... | @@ -1663,7 +1704,7 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa |
| 1663 | 1704 | }); |
| 1664 | 1705 | _ = try self.addInst(.{ |
| 1665 | 1706 | .tag = .@"test", |
| 1666 | | .ops = (Mir.Ops{ |
| 1707 | .ops = (Mir.Ops(Register, Register){ |
| 1667 | 1708 | .reg1 = .rdx, |
| 1668 | 1709 | .reg2 = .rdx, |
| 1669 | 1710 | }).encode(), |
| ... | ... | @@ -1671,7 +1712,7 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa |
| 1671 | 1712 | }); |
| 1672 | 1713 | _ = try self.addInst(.{ |
| 1673 | 1714 | .tag = .cond_mov_eq, |
| 1674 | | .ops = (Mir.Ops{ |
| 1715 | .ops = (Mir.Ops(Register, Register){ |
| 1675 | 1716 | .reg1 = divisor.to64(), |
| 1676 | 1717 | .reg2 = .rdx, |
| 1677 | 1718 | }).encode(), |
| ... | ... | @@ -2058,7 +2099,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 2058 | 2099 | // mov reg, [rbp - 8] |
| 2059 | 2100 | _ = try self.addInst(.{ |
| 2060 | 2101 | .tag = .mov, |
| 2061 | | .ops = (Mir.Ops{ |
| 2102 | .ops = (Mir.Ops(Register, Register){ |
| 2062 | 2103 | .reg1 = addr_reg.to64(), |
| 2063 | 2104 | .reg2 = .rbp, |
| 2064 | 2105 | .flags = 0b01, |
| ... | ... | @@ -2143,7 +2184,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2143 | 2184 | // lea reg, [rbp] |
| 2144 | 2185 | _ = try self.addInst(.{ |
| 2145 | 2186 | .tag = .lea, |
| 2146 | | .ops = (Mir.Ops{ |
| 2187 | .ops = (Mir.Ops(Register, Register){ |
| 2147 | 2188 | .reg1 = addr_reg.to64(), |
| 2148 | 2189 | .reg2 = .rbp, |
| 2149 | 2190 | }).encode(), |
| ... | ... | @@ -2154,7 +2195,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2154 | 2195 | // lea reg, [rbp] |
| 2155 | 2196 | _ = try self.addInst(.{ |
| 2156 | 2197 | .tag = .lea, |
| 2157 | | .ops = (Mir.Ops{ |
| 2198 | .ops = (Mir.Ops(Register, Register){ |
| 2158 | 2199 | .reg1 = addr_reg.to64(), |
| 2159 | 2200 | .reg2 = .rbp, |
| 2160 | 2201 | }).encode(), |
| ... | ... | @@ -2222,7 +2263,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2222 | 2263 | // mov dst_mcv, [dst_mcv] |
| 2223 | 2264 | _ = try self.addInst(.{ |
| 2224 | 2265 | .tag = .mov, |
| 2225 | | .ops = (Mir.Ops{ |
| 2266 | .ops = (Mir.Ops(Register, Register){ |
| 2226 | 2267 | .flags = 0b01, |
| 2227 | 2268 | .reg1 = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)), |
| 2228 | 2269 | .reg2 = dst_mcv.register, |
| ... | ... | @@ -2456,6 +2497,7 @@ fn reuseOperand( |
| 2456 | 2497 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { |
| 2457 | 2498 | const elem_ty = ptr_ty.elemType(); |
| 2458 | 2499 | const abi_size = elem_ty.abiSize(self.target.*); |
| 2500 | std.log.warn("{} => {}, {}", .{ ptr_ty.fmtDebug(), ptr, dst_mcv }); |
| 2459 | 2501 | switch (ptr) { |
| 2460 | 2502 | .none => unreachable, |
| 2461 | 2503 | .undef => unreachable, |
| ... | ... | @@ -2488,7 +2530,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2488 | 2530 | // mov dst_reg, [reg] |
| 2489 | 2531 | _ = try self.addInst(.{ |
| 2490 | 2532 | .tag = .mov, |
| 2491 | | .ops = (Mir.Ops{ |
| 2533 | .ops = (Mir.Ops(Register, Register){ |
| 2492 | 2534 | .reg1 = registerAlias(dst_reg, @intCast(u32, abi_size)), |
| 2493 | 2535 | .reg2 = reg, |
| 2494 | 2536 | .flags = 0b01, |
| ... | ... | @@ -2508,6 +2550,9 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2508 | 2550 | else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}), |
| 2509 | 2551 | } |
| 2510 | 2552 | }, |
| 2553 | .avx_register => { |
| 2554 | return self.fail("TODO load for AVX register", .{}); |
| 2555 | }, |
| 2511 | 2556 | .memory, |
| 2512 | 2557 | .got_load, |
| 2513 | 2558 | .direct_load, |
| ... | ... | @@ -2559,7 +2604,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue |
| 2559 | 2604 | const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); |
| 2560 | 2605 | _ = try self.addInst(.{ |
| 2561 | 2606 | .tag = .lea_pie, |
| 2562 | | .ops = (Mir.Ops{ |
| 2607 | .ops = (Mir.Ops(Register, Register){ |
| 2563 | 2608 | .reg1 = registerAlias(reg, abi_size), |
| 2564 | 2609 | .flags = flags, |
| 2565 | 2610 | }).encode(), |
| ... | ... | @@ -2582,6 +2627,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue |
| 2582 | 2627 | |
| 2583 | 2628 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { |
| 2584 | 2629 | const abi_size = value_ty.abiSize(self.target.*); |
| 2630 | std.log.warn("{} => {}, {} => {}", .{ ptr_ty.fmtDebug(), ptr, value_ty.fmtDebug(), value }); |
| 2585 | 2631 | switch (ptr) { |
| 2586 | 2632 | .none => unreachable, |
| 2587 | 2633 | .undef => unreachable, |
| ... | ... | @@ -2623,7 +2669,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2623 | 2669 | }); |
| 2624 | 2670 | _ = try self.addInst(.{ |
| 2625 | 2671 | .tag = .mov_mem_imm, |
| 2626 | | .ops = (Mir.Ops{ |
| 2672 | .ops = (Mir.Ops(Register, Register){ |
| 2627 | 2673 | .reg1 = reg.to64(), |
| 2628 | 2674 | .flags = switch (abi_size) { |
| 2629 | 2675 | 1 => 0b00, |
| ... | ... | @@ -2645,7 +2691,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2645 | 2691 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); |
| 2646 | 2692 | _ = try self.addInst(.{ |
| 2647 | 2693 | .tag = .mov, |
| 2648 | | .ops = (Mir.Ops{ |
| 2694 | .ops = (Mir.Ops(Register, Register){ |
| 2649 | 2695 | .reg1 = reg.to64(), |
| 2650 | 2696 | .reg2 = tmp_reg.to64(), |
| 2651 | 2697 | .flags = 0b10, |
| ... | ... | @@ -2661,7 +2707,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2661 | 2707 | .register => |src_reg| { |
| 2662 | 2708 | _ = try self.addInst(.{ |
| 2663 | 2709 | .tag = .mov, |
| 2664 | | .ops = (Mir.Ops{ |
| 2710 | .ops = (Mir.Ops(Register, Register){ |
| 2665 | 2711 | .reg1 = reg.to64(), |
| 2666 | 2712 | .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)), |
| 2667 | 2713 | .flags = 0b10, |
| ... | ... | @@ -2689,6 +2735,9 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2689 | 2735 | }, |
| 2690 | 2736 | } |
| 2691 | 2737 | }, |
| 2738 | .avx_register => { |
| 2739 | return self.fail("TODO store for AVX register", .{}); |
| 2740 | }, |
| 2692 | 2741 | .got_load, |
| 2693 | 2742 | .direct_load, |
| 2694 | 2743 | .memory, |
| ... | ... | @@ -2709,7 +2758,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2709 | 2758 | // mov reg, [reg] |
| 2710 | 2759 | _ = try self.addInst(.{ |
| 2711 | 2760 | .tag = .mov, |
| 2712 | | .ops = (Mir.Ops{ |
| 2761 | .ops = (Mir.Ops(Register, Register){ |
| 2713 | 2762 | .reg1 = addr_reg.to64(), |
| 2714 | 2763 | .reg2 = addr_reg.to64(), |
| 2715 | 2764 | .flags = 0b01, |
| ... | ... | @@ -2748,7 +2797,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2748 | 2797 | } |
| 2749 | 2798 | _ = try self.addInst(.{ |
| 2750 | 2799 | .tag = .mov_mem_imm, |
| 2751 | | .ops = (Mir.Ops{ |
| 2800 | .ops = (Mir.Ops(Register, Register){ |
| 2752 | 2801 | .reg1 = addr_reg.to64(), |
| 2753 | 2802 | .flags = flags, |
| 2754 | 2803 | }).encode(), |
| ... | ... | @@ -2758,7 +2807,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2758 | 2807 | .register => |reg| { |
| 2759 | 2808 | _ = try self.addInst(.{ |
| 2760 | 2809 | .tag = .mov, |
| 2761 | | .ops = (Mir.Ops{ |
| 2810 | .ops = (Mir.Ops(Register, Register){ |
| 2762 | 2811 | .reg1 = addr_reg.to64(), |
| 2763 | 2812 | .reg2 = reg, |
| 2764 | 2813 | .flags = 0b10, |
| ... | ... | @@ -2779,7 +2828,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2779 | 2828 | |
| 2780 | 2829 | _ = try self.addInst(.{ |
| 2781 | 2830 | .tag = .mov, |
| 2782 | | .ops = (Mir.Ops{ |
| 2831 | .ops = (Mir.Ops(Register, Register){ |
| 2783 | 2832 | .reg1 = tmp_reg, |
| 2784 | 2833 | .reg2 = tmp_reg, |
| 2785 | 2834 | .flags = 0b01, |
| ... | ... | @@ -2788,7 +2837,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2788 | 2837 | }); |
| 2789 | 2838 | _ = try self.addInst(.{ |
| 2790 | 2839 | .tag = .mov, |
| 2791 | | .ops = (Mir.Ops{ |
| 2840 | .ops = (Mir.Ops(Register, Register){ |
| 2792 | 2841 | .reg1 = addr_reg.to64(), |
| 2793 | 2842 | .reg2 = tmp_reg, |
| 2794 | 2843 | .flags = 0b10, |
| ... | ... | @@ -2806,7 +2855,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2806 | 2855 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); |
| 2807 | 2856 | _ = try self.addInst(.{ |
| 2808 | 2857 | .tag = .mov, |
| 2809 | | .ops = (Mir.Ops{ |
| 2858 | .ops = (Mir.Ops(Register, Register){ |
| 2810 | 2859 | .reg1 = addr_reg.to64(), |
| 2811 | 2860 | .reg2 = tmp_reg, |
| 2812 | 2861 | .flags = 0b10, |
| ... | ... | @@ -2967,7 +3016,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2967 | 3016 | if (signedness == .signed and field_size < 8) { |
| 2968 | 3017 | _ = try self.addInst(.{ |
| 2969 | 3018 | .tag = .mov_sign_extend, |
| 2970 | | .ops = (Mir.Ops{ |
| 3019 | .ops = (Mir.Ops(Register, Register){ |
| 2971 | 3020 | .reg1 = dst_mcv.register, |
| 2972 | 3021 | .reg2 = registerAlias(dst_mcv.register, field_size), |
| 2973 | 3022 | }).encode(), |
| ... | ... | @@ -2998,7 +3047,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2998 | 3047 | }; |
| 2999 | 3048 | _ = try self.addInst(.{ |
| 3000 | 3049 | .tag = .cond_set_byte_overflow, |
| 3001 | | .ops = (Mir.Ops{ |
| 3050 | .ops = (Mir.Ops(Register, Register){ |
| 3002 | 3051 | .reg1 = dst_reg.to8(), |
| 3003 | 3052 | .flags = flags, |
| 3004 | 3053 | }).encode(), |
| ... | ... | @@ -3042,7 +3091,7 @@ fn genShiftBinOpMir(self: *Self, tag: Mir.Inst.Tag, ty: Type, reg: Register, shi |
| 3042 | 3091 | 1 => { |
| 3043 | 3092 | _ = try self.addInst(.{ |
| 3044 | 3093 | .tag = tag, |
| 3045 | | .ops = (Mir.Ops{ |
| 3094 | .ops = (Mir.Ops(Register, Register){ |
| 3046 | 3095 | .reg1 = registerAlias(reg, abi_size), |
| 3047 | 3096 | .flags = 0b00, |
| 3048 | 3097 | }).encode(), |
| ... | ... | @@ -3053,7 +3102,7 @@ fn genShiftBinOpMir(self: *Self, tag: Mir.Inst.Tag, ty: Type, reg: Register, shi |
| 3053 | 3102 | else => { |
| 3054 | 3103 | _ = try self.addInst(.{ |
| 3055 | 3104 | .tag = tag, |
| 3056 | | .ops = (Mir.Ops{ |
| 3105 | .ops = (Mir.Ops(Register, Register){ |
| 3057 | 3106 | .reg1 = registerAlias(reg, abi_size), |
| 3058 | 3107 | .flags = 0b10, |
| 3059 | 3108 | }).encode(), |
| ... | ... | @@ -3074,7 +3123,7 @@ fn genShiftBinOpMir(self: *Self, tag: Mir.Inst.Tag, ty: Type, reg: Register, shi |
| 3074 | 3123 | |
| 3075 | 3124 | _ = try self.addInst(.{ |
| 3076 | 3125 | .tag = tag, |
| 3077 | | .ops = (Mir.Ops{ |
| 3126 | .ops = (Mir.Ops(Register, Register){ |
| 3078 | 3127 | .reg1 = registerAlias(reg, abi_size), |
| 3079 | 3128 | .flags = 0b01, |
| 3080 | 3129 | }).encode(), |
| ... | ... | @@ -3453,17 +3502,20 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3453 | 3502 | .register => |src_reg| { |
| 3454 | 3503 | _ = try self.addInst(.{ |
| 3455 | 3504 | .tag = mir_tag, |
| 3456 | | .ops = (Mir.Ops{ |
| 3505 | .ops = (Mir.Ops(Register, Register){ |
| 3457 | 3506 | .reg1 = registerAlias(dst_reg, abi_size), |
| 3458 | 3507 | .reg2 = registerAlias(src_reg, abi_size), |
| 3459 | 3508 | }).encode(), |
| 3460 | 3509 | .data = undefined, |
| 3461 | 3510 | }); |
| 3462 | 3511 | }, |
| 3512 | .avx_register => { |
| 3513 | return self.fail("TODO genBinOp for AVX register", .{}); |
| 3514 | }, |
| 3463 | 3515 | .immediate => |imm| { |
| 3464 | 3516 | _ = try self.addInst(.{ |
| 3465 | 3517 | .tag = mir_tag, |
| 3466 | | .ops = (Mir.Ops{ |
| 3518 | .ops = (Mir.Ops(Register, Register){ |
| 3467 | 3519 | .reg1 = registerAlias(dst_reg, abi_size), |
| 3468 | 3520 | }).encode(), |
| 3469 | 3521 | .data = .{ .imm = @truncate(u32, imm) }, |
| ... | ... | @@ -3488,7 +3540,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3488 | 3540 | } |
| 3489 | 3541 | _ = try self.addInst(.{ |
| 3490 | 3542 | .tag = mir_tag, |
| 3491 | | .ops = (Mir.Ops{ |
| 3543 | .ops = (Mir.Ops(Register, Register){ |
| 3492 | 3544 | .reg1 = registerAlias(dst_reg, abi_size), |
| 3493 | 3545 | .reg2 = .rbp, |
| 3494 | 3546 | .flags = 0b01, |
| ... | ... | @@ -3498,6 +3550,9 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3498 | 3550 | }, |
| 3499 | 3551 | } |
| 3500 | 3552 | }, |
| 3553 | .avx_register => { |
| 3554 | return self.fail("TODO genBinOp for AVX register", .{}); |
| 3555 | }, |
| 3501 | 3556 | .ptr_stack_offset, .stack_offset => |off| { |
| 3502 | 3557 | if (off > math.maxInt(i32)) { |
| 3503 | 3558 | return self.fail("stack offset too large", .{}); |
| ... | ... | @@ -3515,7 +3570,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3515 | 3570 | .register => |src_reg| { |
| 3516 | 3571 | _ = try self.addInst(.{ |
| 3517 | 3572 | .tag = mir_tag, |
| 3518 | | .ops = (Mir.Ops{ |
| 3573 | .ops = (Mir.Ops(Register, Register){ |
| 3519 | 3574 | .reg1 = .rbp, |
| 3520 | 3575 | .reg2 = registerAlias(src_reg, abi_size), |
| 3521 | 3576 | .flags = 0b10, |
| ... | ... | @@ -3523,6 +3578,9 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3523 | 3578 | .data = .{ .imm = @bitCast(u32, -off) }, |
| 3524 | 3579 | }); |
| 3525 | 3580 | }, |
| 3581 | .avx_register => { |
| 3582 | return self.fail("TODO genBinOp for AVX register", .{}); |
| 3583 | }, |
| 3526 | 3584 | .immediate => |imm| { |
| 3527 | 3585 | const tag: Mir.Inst.Tag = switch (mir_tag) { |
| 3528 | 3586 | .add => .add_mem_imm, |
| ... | ... | @@ -3546,7 +3604,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3546 | 3604 | }); |
| 3547 | 3605 | _ = try self.addInst(.{ |
| 3548 | 3606 | .tag = tag, |
| 3549 | | .ops = (Mir.Ops{ |
| 3607 | .ops = (Mir.Ops(Register, Register){ |
| 3550 | 3608 | .reg1 = .rbp, |
| 3551 | 3609 | .flags = flags, |
| 3552 | 3610 | }).encode(), |
| ... | ... | @@ -3592,6 +3650,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3592 | 3650 | .ptr_stack_offset => unreachable, |
| 3593 | 3651 | .register_overflow_unsigned => unreachable, |
| 3594 | 3652 | .register_overflow_signed => unreachable, |
| 3653 | .avx_register => unreachable, |
| 3595 | 3654 | .register => |dst_reg| { |
| 3596 | 3655 | switch (src_mcv) { |
| 3597 | 3656 | .none => unreachable, |
| ... | ... | @@ -3600,11 +3659,12 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3600 | 3659 | .ptr_stack_offset => unreachable, |
| 3601 | 3660 | .register_overflow_unsigned => unreachable, |
| 3602 | 3661 | .register_overflow_signed => unreachable, |
| 3662 | .avx_register => unreachable, |
| 3603 | 3663 | .register => |src_reg| { |
| 3604 | 3664 | // register, register |
| 3605 | 3665 | _ = try self.addInst(.{ |
| 3606 | 3666 | .tag = .imul_complex, |
| 3607 | | .ops = (Mir.Ops{ |
| 3667 | .ops = (Mir.Ops(Register, Register){ |
| 3608 | 3668 | .reg1 = registerAlias(dst_reg, abi_size), |
| 3609 | 3669 | .reg2 = registerAlias(src_reg, abi_size), |
| 3610 | 3670 | }).encode(), |
| ... | ... | @@ -3617,7 +3677,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3617 | 3677 | if (math.minInt(i32) <= imm and imm <= math.maxInt(i32)) { |
| 3618 | 3678 | _ = try self.addInst(.{ |
| 3619 | 3679 | .tag = .imul_complex, |
| 3620 | | .ops = (Mir.Ops{ |
| 3680 | .ops = (Mir.Ops(Register, Register){ |
| 3621 | 3681 | .reg1 = dst_reg.to32(), |
| 3622 | 3682 | .reg2 = dst_reg.to32(), |
| 3623 | 3683 | .flags = 0b10, |
| ... | ... | @@ -3633,7 +3693,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3633 | 3693 | .stack_offset => |off| { |
| 3634 | 3694 | _ = try self.addInst(.{ |
| 3635 | 3695 | .tag = .imul_complex, |
| 3636 | | .ops = (Mir.Ops{ |
| 3696 | .ops = (Mir.Ops(Register, Register){ |
| 3637 | 3697 | .reg1 = registerAlias(dst_reg, abi_size), |
| 3638 | 3698 | .reg2 = .rbp, |
| 3639 | 3699 | .flags = 0b01, |
| ... | ... | @@ -3663,6 +3723,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3663 | 3723 | .ptr_stack_offset => unreachable, |
| 3664 | 3724 | .register_overflow_unsigned => unreachable, |
| 3665 | 3725 | .register_overflow_signed => unreachable, |
| 3726 | .avx_register => unreachable, |
| 3666 | 3727 | .register => |src_reg| { |
| 3667 | 3728 | // copy dst to a register |
| 3668 | 3729 | const dst_reg = try self.copyToTmpRegister(dst_ty, dst_mcv); |
| ... | ... | @@ -3670,7 +3731,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3670 | 3731 | // register, register |
| 3671 | 3732 | _ = try self.addInst(.{ |
| 3672 | 3733 | .tag = .imul_complex, |
| 3673 | | .ops = (Mir.Ops{ |
| 3734 | .ops = (Mir.Ops(Register, Register){ |
| 3674 | 3735 | .reg1 = registerAlias(dst_reg, abi_size), |
| 3675 | 3736 | .reg2 = registerAlias(src_reg, abi_size), |
| 3676 | 3737 | }).encode(), |
| ... | ... | @@ -3865,6 +3926,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3865 | 3926 | .ptr_stack_offset => { |
| 3866 | 3927 | return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{}); |
| 3867 | 3928 | }, |
| 3929 | .avx_register => { |
| 3930 | return self.fail("TODO implement calling with MCValue.avx_register arg", .{}); |
| 3931 | }, |
| 3868 | 3932 | .undef => unreachable, |
| 3869 | 3933 | .immediate => unreachable, |
| 3870 | 3934 | .unreach => unreachable, |
| ... | ... | @@ -3883,7 +3947,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3883 | 3947 | // Adjust the stack |
| 3884 | 3948 | _ = try self.addInst(.{ |
| 3885 | 3949 | .tag = .sub, |
| 3886 | | .ops = (Mir.Ops{ |
| 3950 | .ops = (Mir.Ops(Register, Register){ |
| 3887 | 3951 | .reg1 = .rsp, |
| 3888 | 3952 | }).encode(), |
| 3889 | 3953 | .data = .{ .imm = info.stack_byte_count }, |
| ... | ... | @@ -3909,7 +3973,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3909 | 3973 | unreachable; |
| 3910 | 3974 | _ = try self.addInst(.{ |
| 3911 | 3975 | .tag = .call, |
| 3912 | | .ops = (Mir.Ops{ |
| 3976 | .ops = (Mir.Ops(Register, Register){ |
| 3913 | 3977 | .flags = 0b01, |
| 3914 | 3978 | }).encode(), |
| 3915 | 3979 | .data = .{ .imm = @truncate(u32, got_addr) }, |
| ... | ... | @@ -3925,7 +3989,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3925 | 3989 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); |
| 3926 | 3990 | _ = try self.addInst(.{ |
| 3927 | 3991 | .tag = .call, |
| 3928 | | .ops = (Mir.Ops{ |
| 3992 | .ops = (Mir.Ops(Register, Register){ |
| 3929 | 3993 | .reg1 = .rax, |
| 3930 | 3994 | .flags = 0b01, |
| 3931 | 3995 | }).encode(), |
| ... | ... | @@ -3943,7 +4007,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3943 | 4007 | // callq *%rax |
| 3944 | 4008 | _ = try self.addInst(.{ |
| 3945 | 4009 | .tag = .call, |
| 3946 | | .ops = (Mir.Ops{ |
| 4010 | .ops = (Mir.Ops(Register, Register){ |
| 3947 | 4011 | .reg1 = .rax, |
| 3948 | 4012 | .flags = 0b01, |
| 3949 | 4013 | }).encode(), |
| ... | ... | @@ -3978,7 +4042,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3978 | 4042 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); |
| 3979 | 4043 | _ = try self.addInst(.{ |
| 3980 | 4044 | .tag = .call, |
| 3981 | | .ops = (Mir.Ops{ |
| 4045 | .ops = (Mir.Ops(Register, Register){ |
| 3982 | 4046 | .reg1 = .rax, |
| 3983 | 4047 | .flags = 0b01, |
| 3984 | 4048 | }).encode(), |
| ... | ... | @@ -3996,7 +4060,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3996 | 4060 | const fn_got_addr = got_addr + got_index * ptr_bytes; |
| 3997 | 4061 | _ = try self.addInst(.{ |
| 3998 | 4062 | .tag = .call, |
| 3999 | | .ops = (Mir.Ops{ |
| 4063 | .ops = (Mir.Ops(Register, Register){ |
| 4000 | 4064 | .flags = 0b01, |
| 4001 | 4065 | }).encode(), |
| 4002 | 4066 | .data = .{ .imm = @intCast(u32, fn_got_addr) }, |
| ... | ... | @@ -4008,7 +4072,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 4008 | 4072 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); |
| 4009 | 4073 | _ = try self.addInst(.{ |
| 4010 | 4074 | .tag = .call, |
| 4011 | | .ops = (Mir.Ops{ |
| 4075 | .ops = (Mir.Ops(Register, Register){ |
| 4012 | 4076 | .reg1 = .rax, |
| 4013 | 4077 | .flags = 0b01, |
| 4014 | 4078 | }).encode(), |
| ... | ... | @@ -4021,7 +4085,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 4021 | 4085 | // Readjust the stack |
| 4022 | 4086 | _ = try self.addInst(.{ |
| 4023 | 4087 | .tag = .add, |
| 4024 | | .ops = (Mir.Ops{ |
| 4088 | .ops = (Mir.Ops(Register, Register){ |
| 4025 | 4089 | .reg1 = .rsp, |
| 4026 | 4090 | }).encode(), |
| 4027 | 4091 | .data = .{ .imm = info.stack_byte_count }, |
| ... | ... | @@ -4081,7 +4145,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 4081 | 4145 | // which is available if the jump is 127 bytes or less forward. |
| 4082 | 4146 | const jmp_reloc = try self.addInst(.{ |
| 4083 | 4147 | .tag = .jmp, |
| 4084 | | .ops = (Mir.Ops{ |
| 4148 | .ops = (Mir.Ops(Register, Register){ |
| 4085 | 4149 | .flags = 0b00, |
| 4086 | 4150 | }).encode(), |
| 4087 | 4151 | .data = .{ .inst = undefined }, |
| ... | ... | @@ -4116,7 +4180,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 4116 | 4180 | // which is available if the jump is 127 bytes or less forward. |
| 4117 | 4181 | const jmp_reloc = try self.addInst(.{ |
| 4118 | 4182 | .tag = .jmp, |
| 4119 | | .ops = (Mir.Ops{ |
| 4183 | .ops = (Mir.Ops(Register, Register){ |
| 4120 | 4184 | .flags = 0b00, |
| 4121 | 4185 | }).encode(), |
| 4122 | 4186 | .data = .{ .inst = undefined }, |
| ... | ... | @@ -4362,7 +4426,7 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 { |
| 4362 | 4426 | Mir.Inst.Tag.cond_jmp_greater_less; |
| 4363 | 4427 | return self.addInst(.{ |
| 4364 | 4428 | .tag = tag, |
| 4365 | | .ops = (Mir.Ops{ |
| 4429 | .ops = (Mir.Ops(Register, Register){ |
| 4366 | 4430 | .flags = flags, |
| 4367 | 4431 | }).encode(), |
| 4368 | 4432 | .data = .{ .inst = undefined }, |
| ... | ... | @@ -4372,7 +4436,7 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 { |
| 4372 | 4436 | try self.spillCompareFlagsIfOccupied(); |
| 4373 | 4437 | _ = try self.addInst(.{ |
| 4374 | 4438 | .tag = .@"test", |
| 4375 | | .ops = (Mir.Ops{ |
| 4439 | .ops = (Mir.Ops(Register, Register){ |
| 4376 | 4440 | .reg1 = reg, |
| 4377 | 4441 | .flags = 0b00, |
| 4378 | 4442 | }).encode(), |
| ... | ... | @@ -4380,7 +4444,7 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 { |
| 4380 | 4444 | }); |
| 4381 | 4445 | return self.addInst(.{ |
| 4382 | 4446 | .tag = .cond_jmp_eq_ne, |
| 4383 | | .ops = (Mir.Ops{ |
| 4447 | .ops = (Mir.Ops(Register, Register){ |
| 4384 | 4448 | .flags = 0b01, |
| 4385 | 4449 | }).encode(), |
| 4386 | 4450 | .data = .{ .inst = undefined }, |
| ... | ... | @@ -4776,7 +4840,7 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { |
| 4776 | 4840 | try self.genBody(body); |
| 4777 | 4841 | _ = try self.addInst(.{ |
| 4778 | 4842 | .tag = .jmp, |
| 4779 | | .ops = (Mir.Ops{ |
| 4843 | .ops = (Mir.Ops(Register, Register){ |
| 4780 | 4844 | .flags = 0b00, |
| 4781 | 4845 | }).encode(), |
| 4782 | 4846 | .data = .{ .inst = jmp_target }, |
| ... | ... | @@ -4829,7 +4893,7 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u |
| 4829 | 4893 | .immediate => |imm| { |
| 4830 | 4894 | _ = try self.addInst(.{ |
| 4831 | 4895 | .tag = .xor, |
| 4832 | | .ops = (Mir.Ops{ |
| 4896 | .ops = (Mir.Ops(Register, Register){ |
| 4833 | 4897 | .reg1 = registerAlias(cond_reg, abi_size), |
| 4834 | 4898 | }).encode(), |
| 4835 | 4899 | .data = .{ .imm = @intCast(u32, imm) }, |
| ... | ... | @@ -4838,7 +4902,7 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u |
| 4838 | 4902 | .register => |reg| { |
| 4839 | 4903 | _ = try self.addInst(.{ |
| 4840 | 4904 | .tag = .xor, |
| 4841 | | .ops = (Mir.Ops{ |
| 4905 | .ops = (Mir.Ops(Register, Register){ |
| 4842 | 4906 | .reg1 = registerAlias(cond_reg, abi_size), |
| 4843 | 4907 | .reg2 = registerAlias(reg, abi_size), |
| 4844 | 4908 | }).encode(), |
| ... | ... | @@ -4860,7 +4924,7 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u |
| 4860 | 4924 | |
| 4861 | 4925 | _ = try self.addInst(.{ |
| 4862 | 4926 | .tag = .@"test", |
| 4863 | | .ops = (Mir.Ops{ |
| 4927 | .ops = (Mir.Ops(Register, Register){ |
| 4864 | 4928 | .reg1 = registerAlias(cond_reg, abi_size), |
| 4865 | 4929 | .reg2 = registerAlias(cond_reg, abi_size), |
| 4866 | 4930 | }).encode(), |
| ... | ... | @@ -4868,7 +4932,7 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u |
| 4868 | 4932 | }); |
| 4869 | 4933 | return self.addInst(.{ |
| 4870 | 4934 | .tag = .cond_jmp_eq_ne, |
| 4871 | | .ops = (Mir.Ops{ |
| 4935 | .ops = (Mir.Ops(Register, Register){ |
| 4872 | 4936 | .flags = 0b00, |
| 4873 | 4937 | }).encode(), |
| 4874 | 4938 | .data = .{ .inst = undefined }, |
| ... | ... | @@ -5020,6 +5084,12 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { |
| 5020 | 5084 | try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv); |
| 5021 | 5085 | break :blk new_mcv; |
| 5022 | 5086 | }, |
| 5087 | .avx_register => blk: { |
| 5088 | // TODO not needed; return operand_mcv ones we can transfer between XMM registers |
| 5089 | const new_mcv = try self.allocRegOrMem(block, false); |
| 5090 | try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv); |
| 5091 | break :blk new_mcv; |
| 5092 | }, |
| 5023 | 5093 | else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}), |
| 5024 | 5094 | }; |
| 5025 | 5095 | } else { |
| ... | ... | @@ -5036,7 +5106,7 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void { |
| 5036 | 5106 | // Leave the jump offset undefined |
| 5037 | 5107 | const jmp_reloc = try self.addInst(.{ |
| 5038 | 5108 | .tag = .jmp, |
| 5039 | | .ops = (Mir.Ops{ |
| 5109 | .ops = (Mir.Ops(Register, Register){ |
| 5040 | 5110 | .flags = 0b00, |
| 5041 | 5111 | }).encode(), |
| 5042 | 5112 | .data = .{ .inst = undefined }, |
| ... | ... | @@ -5126,7 +5196,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 5126 | 5196 | }; |
| 5127 | 5197 | _ = try self.addInst(.{ |
| 5128 | 5198 | .tag = .push, |
| 5129 | | .ops = (Mir.Ops{ |
| 5199 | .ops = (Mir.Ops(Register, Register){ |
| 5130 | 5200 | .flags = 0b10, |
| 5131 | 5201 | }).encode(), |
| 5132 | 5202 | .data = .{ .imm = n }, |
| ... | ... | @@ -5137,7 +5207,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 5137 | 5207 | return self.fail("unrecognized register: '{s}'", .{reg_name}); |
| 5138 | 5208 | _ = try self.addInst(.{ |
| 5139 | 5209 | .tag = .push, |
| 5140 | | .ops = (Mir.Ops{ |
| 5210 | .ops = (Mir.Ops(Register, Register){ |
| 5141 | 5211 | .reg1 = reg, |
| 5142 | 5212 | }).encode(), |
| 5143 | 5213 | .data = undefined, |
| ... | ... | @@ -5151,7 +5221,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 5151 | 5221 | return self.fail("unrecognized register: '{s}'", .{reg_name}); |
| 5152 | 5222 | _ = try self.addInst(.{ |
| 5153 | 5223 | .tag = .pop, |
| 5154 | | .ops = (Mir.Ops{ |
| 5224 | .ops = (Mir.Ops(Register, Register){ |
| 5155 | 5225 | .reg1 = reg, |
| 5156 | 5226 | }).encode(), |
| 5157 | 5227 | .data = undefined, |
| ... | ... | @@ -5217,6 +5287,7 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { |
| 5217 | 5287 | .none => return, |
| 5218 | 5288 | .immediate => unreachable, |
| 5219 | 5289 | .register => |reg| return self.genSetReg(ty, reg, val), |
| 5290 | .avx_register => |reg| return self.genSetAvxReg(ty, reg, val), |
| 5220 | 5291 | .stack_offset => |off| return self.genSetStack(ty, off, val, .{}), |
| 5221 | 5292 | .memory => { |
| 5222 | 5293 | return self.fail("TODO implement setRegOrMem for memory", .{}); |
| ... | ... | @@ -5247,6 +5318,9 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5247 | 5318 | .register_overflow_unsigned, |
| 5248 | 5319 | .register_overflow_signed, |
| 5249 | 5320 | => return self.fail("TODO genSetStackArg for register with overflow bit", .{}), |
| 5321 | .avx_register => { |
| 5322 | return self.fail("TODO genSetStackArg for AVX register", .{}); |
| 5323 | }, |
| 5250 | 5324 | .compare_flags_unsigned, |
| 5251 | 5325 | .compare_flags_signed, |
| 5252 | 5326 | => { |
| ... | ... | @@ -5265,7 +5339,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5265 | 5339 | }); |
| 5266 | 5340 | _ = try self.addInst(.{ |
| 5267 | 5341 | .tag = .mov_mem_imm, |
| 5268 | | .ops = (Mir.Ops{ |
| 5342 | .ops = (Mir.Ops(Register, Register){ |
| 5269 | 5343 | .reg1 = .rsp, |
| 5270 | 5344 | .flags = switch (abi_size) { |
| 5271 | 5345 | 1 => 0b00, |
| ... | ... | @@ -5301,7 +5375,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5301 | 5375 | .register => |reg| { |
| 5302 | 5376 | _ = try self.addInst(.{ |
| 5303 | 5377 | .tag = .mov, |
| 5304 | | .ops = (Mir.Ops{ |
| 5378 | .ops = (Mir.Ops(Register, Register){ |
| 5305 | 5379 | .reg1 = .rsp, |
| 5306 | 5380 | .reg2 = registerAlias(reg, @intCast(u32, abi_size)), |
| 5307 | 5381 | .flags = 0b10, |
| ... | ... | @@ -5368,7 +5442,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5368 | 5442 | }; |
| 5369 | 5443 | _ = try self.addInst(.{ |
| 5370 | 5444 | .tag = .cond_set_byte_overflow, |
| 5371 | | .ops = (Mir.Ops{ |
| 5445 | .ops = (Mir.Ops(Register, Register){ |
| 5372 | 5446 | .reg1 = tmp_reg.to8(), |
| 5373 | 5447 | .flags = flags, |
| 5374 | 5448 | }).encode(), |
| ... | ... | @@ -5398,7 +5472,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5398 | 5472 | }); |
| 5399 | 5473 | _ = try self.addInst(.{ |
| 5400 | 5474 | .tag = .mov_mem_imm, |
| 5401 | | .ops = (Mir.Ops{ |
| 5475 | .ops = (Mir.Ops(Register, Register){ |
| 5402 | 5476 | .reg1 = base_reg, |
| 5403 | 5477 | .flags = switch (abi_size) { |
| 5404 | 5478 | 1 => 0b00, |
| ... | ... | @@ -5420,7 +5494,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5420 | 5494 | }); |
| 5421 | 5495 | _ = try self.addInst(.{ |
| 5422 | 5496 | .tag = .mov_mem_imm, |
| 5423 | | .ops = (Mir.Ops{ |
| 5497 | .ops = (Mir.Ops(Register, Register){ |
| 5424 | 5498 | .reg1 = base_reg, |
| 5425 | 5499 | .flags = 0b10, |
| 5426 | 5500 | }).encode(), |
| ... | ... | @@ -5434,7 +5508,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5434 | 5508 | }); |
| 5435 | 5509 | _ = try self.addInst(.{ |
| 5436 | 5510 | .tag = .mov_mem_imm, |
| 5437 | | .ops = (Mir.Ops{ |
| 5511 | .ops = (Mir.Ops(Register, Register){ |
| 5438 | 5512 | .reg1 = base_reg, |
| 5439 | 5513 | .flags = 0b10, |
| 5440 | 5514 | }).encode(), |
| ... | ... | @@ -5466,7 +5540,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5466 | 5540 | |
| 5467 | 5541 | _ = try self.addInst(.{ |
| 5468 | 5542 | .tag = .mov, |
| 5469 | | .ops = (Mir.Ops{ |
| 5543 | .ops = (Mir.Ops(Register, Register){ |
| 5470 | 5544 | .reg1 = base_reg, |
| 5471 | 5545 | .reg2 = registerAlias(tmp_reg, nearest_power_of_two), |
| 5472 | 5546 | .flags = 0b10, |
| ... | ... | @@ -5484,7 +5558,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5484 | 5558 | } else { |
| 5485 | 5559 | _ = try self.addInst(.{ |
| 5486 | 5560 | .tag = .mov, |
| 5487 | | .ops = (Mir.Ops{ |
| 5561 | .ops = (Mir.Ops(Register, Register){ |
| 5488 | 5562 | .reg1 = base_reg, |
| 5489 | 5563 | .reg2 = registerAlias(reg, @intCast(u32, abi_size)), |
| 5490 | 5564 | .flags = 0b10, |
| ... | ... | @@ -5493,6 +5567,27 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5493 | 5567 | }); |
| 5494 | 5568 | } |
| 5495 | 5569 | }, |
| 5570 | .avx_register => |reg| { |
| 5571 | const base_reg = opts.dest_stack_base orelse .rbp; |
| 5572 | switch (ty.zigTypeTag()) { |
| 5573 | .Float => switch (ty.tag()) { |
| 5574 | .f32 => return self.fail("TODO genSetStack for AVX register for f32", .{}), |
| 5575 | .f64 => { |
| 5576 | _ = try self.addInst(.{ |
| 5577 | .tag = .mov_f64, |
| 5578 | .ops = (Mir.Ops(Register, AvxRegister){ |
| 5579 | .reg1 = base_reg, |
| 5580 | .reg2 = reg.to128(), |
| 5581 | .flags = 0b01, |
| 5582 | }).encode(), |
| 5583 | .data = .{ .imm = @bitCast(u32, -stack_offset) }, |
| 5584 | }); |
| 5585 | }, |
| 5586 | else => return self.fail("TODO genSetStack for AVX register for type {}", .{ty.fmtDebug()}), |
| 5587 | }, |
| 5588 | else => return self.fail("TODO genSetStack for AVX register for type {}", .{ty.fmtDebug()}), |
| 5589 | } |
| 5590 | }, |
| 5496 | 5591 | .memory, |
| 5497 | 5592 | .got_load, |
| 5498 | 5593 | .direct_load, |
| ... | ... | @@ -5569,7 +5664,7 @@ fn genInlineMemcpy( |
| 5569 | 5664 | .ptr_stack_offset, .stack_offset => |off| { |
| 5570 | 5665 | _ = try self.addInst(.{ |
| 5571 | 5666 | .tag = .lea, |
| 5572 | | .ops = (Mir.Ops{ |
| 5667 | .ops = (Mir.Ops(Register, Register){ |
| 5573 | 5668 | .reg1 = dst_addr_reg.to64(), |
| 5574 | 5669 | .reg2 = opts.dest_stack_base orelse .rbp, |
| 5575 | 5670 | }).encode(), |
| ... | ... | @@ -5579,7 +5674,7 @@ fn genInlineMemcpy( |
| 5579 | 5674 | .register => |reg| { |
| 5580 | 5675 | _ = try self.addInst(.{ |
| 5581 | 5676 | .tag = .mov, |
| 5582 | | .ops = (Mir.Ops{ |
| 5677 | .ops = (Mir.Ops(Register, Register){ |
| 5583 | 5678 | .reg1 = registerAlias(dst_addr_reg, @divExact(reg.size(), 8)), |
| 5584 | 5679 | .reg2 = reg, |
| 5585 | 5680 | }).encode(), |
| ... | ... | @@ -5604,7 +5699,7 @@ fn genInlineMemcpy( |
| 5604 | 5699 | .ptr_stack_offset, .stack_offset => |off| { |
| 5605 | 5700 | _ = try self.addInst(.{ |
| 5606 | 5701 | .tag = .lea, |
| 5607 | | .ops = (Mir.Ops{ |
| 5702 | .ops = (Mir.Ops(Register, Register){ |
| 5608 | 5703 | .reg1 = src_addr_reg.to64(), |
| 5609 | 5704 | .reg2 = opts.source_stack_base orelse .rbp, |
| 5610 | 5705 | }).encode(), |
| ... | ... | @@ -5614,7 +5709,7 @@ fn genInlineMemcpy( |
| 5614 | 5709 | .register => |reg| { |
| 5615 | 5710 | _ = try self.addInst(.{ |
| 5616 | 5711 | .tag = .mov, |
| 5617 | | .ops = (Mir.Ops{ |
| 5712 | .ops = (Mir.Ops(Register, Register){ |
| 5618 | 5713 | .reg1 = registerAlias(src_addr_reg, @divExact(reg.size(), 8)), |
| 5619 | 5714 | .reg2 = reg, |
| 5620 | 5715 | }).encode(), |
| ... | ... | @@ -5637,7 +5732,7 @@ fn genInlineMemcpy( |
| 5637 | 5732 | // mov rcx, 0 |
| 5638 | 5733 | _ = try self.addInst(.{ |
| 5639 | 5734 | .tag = .mov, |
| 5640 | | .ops = (Mir.Ops{ |
| 5735 | .ops = (Mir.Ops(Register, Register){ |
| 5641 | 5736 | .reg1 = .rcx, |
| 5642 | 5737 | }).encode(), |
| 5643 | 5738 | .data = .{ .imm = 0 }, |
| ... | ... | @@ -5646,7 +5741,7 @@ fn genInlineMemcpy( |
| 5646 | 5741 | // mov rax, 0 |
| 5647 | 5742 | _ = try self.addInst(.{ |
| 5648 | 5743 | .tag = .mov, |
| 5649 | | .ops = (Mir.Ops{ |
| 5744 | .ops = (Mir.Ops(Register, Register){ |
| 5650 | 5745 | .reg1 = .rax, |
| 5651 | 5746 | }).encode(), |
| 5652 | 5747 | .data = .{ .imm = 0 }, |
| ... | ... | @@ -5656,7 +5751,7 @@ fn genInlineMemcpy( |
| 5656 | 5751 | // cmp count, 0 |
| 5657 | 5752 | const loop_start = try self.addInst(.{ |
| 5658 | 5753 | .tag = .cmp, |
| 5659 | | .ops = (Mir.Ops{ |
| 5754 | .ops = (Mir.Ops(Register, Register){ |
| 5660 | 5755 | .reg1 = count_reg, |
| 5661 | 5756 | }).encode(), |
| 5662 | 5757 | .data = .{ .imm = 0 }, |
| ... | ... | @@ -5665,14 +5760,14 @@ fn genInlineMemcpy( |
| 5665 | 5760 | // je end |
| 5666 | 5761 | const loop_reloc = try self.addInst(.{ |
| 5667 | 5762 | .tag = .cond_jmp_eq_ne, |
| 5668 | | .ops = (Mir.Ops{ .flags = 0b01 }).encode(), |
| 5763 | .ops = (Mir.Ops(Register, Register){ .flags = 0b01 }).encode(), |
| 5669 | 5764 | .data = .{ .inst = undefined }, |
| 5670 | 5765 | }); |
| 5671 | 5766 | |
| 5672 | 5767 | // mov tmp, [addr + rcx] |
| 5673 | 5768 | _ = try self.addInst(.{ |
| 5674 | 5769 | .tag = .mov_scale_src, |
| 5675 | | .ops = (Mir.Ops{ |
| 5770 | .ops = (Mir.Ops(Register, Register){ |
| 5676 | 5771 | .reg1 = tmp_reg.to8(), |
| 5677 | 5772 | .reg2 = src_addr_reg, |
| 5678 | 5773 | }).encode(), |
| ... | ... | @@ -5682,7 +5777,7 @@ fn genInlineMemcpy( |
| 5682 | 5777 | // mov [stack_offset + rax], tmp |
| 5683 | 5778 | _ = try self.addInst(.{ |
| 5684 | 5779 | .tag = .mov_scale_dst, |
| 5685 | | .ops = (Mir.Ops{ |
| 5780 | .ops = (Mir.Ops(Register, Register){ |
| 5686 | 5781 | .reg1 = dst_addr_reg, |
| 5687 | 5782 | .reg2 = tmp_reg.to8(), |
| 5688 | 5783 | }).encode(), |
| ... | ... | @@ -5692,7 +5787,7 @@ fn genInlineMemcpy( |
| 5692 | 5787 | // add rcx, 1 |
| 5693 | 5788 | _ = try self.addInst(.{ |
| 5694 | 5789 | .tag = .add, |
| 5695 | | .ops = (Mir.Ops{ |
| 5790 | .ops = (Mir.Ops(Register, Register){ |
| 5696 | 5791 | .reg1 = .rcx, |
| 5697 | 5792 | }).encode(), |
| 5698 | 5793 | .data = .{ .imm = 1 }, |
| ... | ... | @@ -5701,7 +5796,7 @@ fn genInlineMemcpy( |
| 5701 | 5796 | // add rax, 1 |
| 5702 | 5797 | _ = try self.addInst(.{ |
| 5703 | 5798 | .tag = .add, |
| 5704 | | .ops = (Mir.Ops{ |
| 5799 | .ops = (Mir.Ops(Register, Register){ |
| 5705 | 5800 | .reg1 = .rax, |
| 5706 | 5801 | }).encode(), |
| 5707 | 5802 | .data = .{ .imm = 1 }, |
| ... | ... | @@ -5710,7 +5805,7 @@ fn genInlineMemcpy( |
| 5710 | 5805 | // sub count, 1 |
| 5711 | 5806 | _ = try self.addInst(.{ |
| 5712 | 5807 | .tag = .sub, |
| 5713 | | .ops = (Mir.Ops{ |
| 5808 | .ops = (Mir.Ops(Register, Register){ |
| 5714 | 5809 | .reg1 = count_reg, |
| 5715 | 5810 | }).encode(), |
| 5716 | 5811 | .data = .{ .imm = 1 }, |
| ... | ... | @@ -5719,7 +5814,7 @@ fn genInlineMemcpy( |
| 5719 | 5814 | // jmp loop |
| 5720 | 5815 | _ = try self.addInst(.{ |
| 5721 | 5816 | .tag = .jmp, |
| 5722 | | .ops = (Mir.Ops{ .flags = 0b00 }).encode(), |
| 5817 | .ops = (Mir.Ops(Register, Register){ .flags = 0b00 }).encode(), |
| 5723 | 5818 | .data = .{ .inst = loop_start }, |
| 5724 | 5819 | }); |
| 5725 | 5820 | |
| ... | ... | @@ -5751,7 +5846,7 @@ fn genInlineMemset( |
| 5751 | 5846 | .ptr_stack_offset, .stack_offset => |off| { |
| 5752 | 5847 | _ = try self.addInst(.{ |
| 5753 | 5848 | .tag = .lea, |
| 5754 | | .ops = (Mir.Ops{ |
| 5849 | .ops = (Mir.Ops(Register, Register){ |
| 5755 | 5850 | .reg1 = addr_reg.to64(), |
| 5756 | 5851 | .reg2 = opts.dest_stack_base orelse .rbp, |
| 5757 | 5852 | }).encode(), |
| ... | ... | @@ -5761,7 +5856,7 @@ fn genInlineMemset( |
| 5761 | 5856 | .register => |reg| { |
| 5762 | 5857 | _ = try self.addInst(.{ |
| 5763 | 5858 | .tag = .mov, |
| 5764 | | .ops = (Mir.Ops{ |
| 5859 | .ops = (Mir.Ops(Register, Register){ |
| 5765 | 5860 | .reg1 = registerAlias(addr_reg, @divExact(reg.size(), 8)), |
| 5766 | 5861 | .reg2 = reg, |
| 5767 | 5862 | }).encode(), |
| ... | ... | @@ -5782,7 +5877,7 @@ fn genInlineMemset( |
| 5782 | 5877 | // cmp rax, -1 |
| 5783 | 5878 | const loop_start = try self.addInst(.{ |
| 5784 | 5879 | .tag = .cmp, |
| 5785 | | .ops = (Mir.Ops{ |
| 5880 | .ops = (Mir.Ops(Register, Register){ |
| 5786 | 5881 | .reg1 = .rax, |
| 5787 | 5882 | }).encode(), |
| 5788 | 5883 | .data = .{ .imm = @bitCast(u32, @as(i32, -1)) }, |
| ... | ... | @@ -5791,7 +5886,7 @@ fn genInlineMemset( |
| 5791 | 5886 | // je end |
| 5792 | 5887 | const loop_reloc = try self.addInst(.{ |
| 5793 | 5888 | .tag = .cond_jmp_eq_ne, |
| 5794 | | .ops = (Mir.Ops{ .flags = 0b01 }).encode(), |
| 5889 | .ops = (Mir.Ops(Register, Register){ .flags = 0b01 }).encode(), |
| 5795 | 5890 | .data = .{ .inst = undefined }, |
| 5796 | 5891 | }); |
| 5797 | 5892 | |
| ... | ... | @@ -5807,7 +5902,7 @@ fn genInlineMemset( |
| 5807 | 5902 | }); |
| 5808 | 5903 | _ = try self.addInst(.{ |
| 5809 | 5904 | .tag = .mov_mem_index_imm, |
| 5810 | | .ops = (Mir.Ops{ |
| 5905 | .ops = (Mir.Ops(Register, Register){ |
| 5811 | 5906 | .reg1 = addr_reg, |
| 5812 | 5907 | }).encode(), |
| 5813 | 5908 | .data = .{ .payload = payload }, |
| ... | ... | @@ -5819,7 +5914,7 @@ fn genInlineMemset( |
| 5819 | 5914 | // sub rax, 1 |
| 5820 | 5915 | _ = try self.addInst(.{ |
| 5821 | 5916 | .tag = .sub, |
| 5822 | | .ops = (Mir.Ops{ |
| 5917 | .ops = (Mir.Ops(Register, Register){ |
| 5823 | 5918 | .reg1 = .rax, |
| 5824 | 5919 | }).encode(), |
| 5825 | 5920 | .data = .{ .imm = 1 }, |
| ... | ... | @@ -5828,7 +5923,7 @@ fn genInlineMemset( |
| 5828 | 5923 | // jmp loop |
| 5829 | 5924 | _ = try self.addInst(.{ |
| 5830 | 5925 | .tag = .jmp, |
| 5831 | | .ops = (Mir.Ops{ .flags = 0b00 }).encode(), |
| 5926 | .ops = (Mir.Ops(Register, Register){ .flags = 0b00 }).encode(), |
| 5832 | 5927 | .data = .{ .inst = loop_start }, |
| 5833 | 5928 | }); |
| 5834 | 5929 | |
| ... | ... | @@ -5836,6 +5931,43 @@ fn genInlineMemset( |
| 5836 | 5931 | try self.performReloc(loop_reloc); |
| 5837 | 5932 | } |
| 5838 | 5933 | |
| 5934 | fn genSetAvxReg(self: *Self, ty: Type, reg: AvxRegister, mcv: MCValue) InnerError!void { |
| 5935 | switch (mcv) { |
| 5936 | .dead => unreachable, |
| 5937 | .register_overflow_unsigned, |
| 5938 | .register_overflow_signed, |
| 5939 | => unreachable, |
| 5940 | .stack_offset => |off| { |
| 5941 | if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) { |
| 5942 | return self.fail("stack offset too large", .{}); |
| 5943 | } |
| 5944 | |
| 5945 | switch (ty.zigTypeTag()) { |
| 5946 | .Float => { |
| 5947 | switch (ty.tag()) { |
| 5948 | .f32 => return self.fail("TODO genSetAvxReg from stack offset for f32", .{}), |
| 5949 | .f64 => { |
| 5950 | _ = try self.addInst(.{ |
| 5951 | .tag = .mov_f64, |
| 5952 | .ops = (Mir.Ops(AvxRegister, Register){ |
| 5953 | .reg1 = reg.to128(), |
| 5954 | .reg2 = .rbp, |
| 5955 | }).encode(), |
| 5956 | .data = .{ .imm = @bitCast(u32, -off) }, |
| 5957 | }); |
| 5958 | }, |
| 5959 | else => return self.fail("TODO genSetAvxReg from stack offset for {}", .{ty.fmtDebug()}), |
| 5960 | } |
| 5961 | }, |
| 5962 | else => return self.fail("TODO genSetAvxReg from stack offset for type {}", .{ty.fmtDebug()}), |
| 5963 | } |
| 5964 | }, |
| 5965 | else => |other| { |
| 5966 | return self.fail("TODO genSetAvxReg from {}", .{other}); |
| 5967 | }, |
| 5968 | } |
| 5969 | } |
| 5970 | |
| 5839 | 5971 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { |
| 5840 | 5972 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 5841 | 5973 | switch (mcv) { |
| ... | ... | @@ -5843,13 +5975,14 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5843 | 5975 | .register_overflow_unsigned, |
| 5844 | 5976 | .register_overflow_signed, |
| 5845 | 5977 | => unreachable, |
| 5978 | .avx_register => unreachable, |
| 5846 | 5979 | .ptr_stack_offset => |off| { |
| 5847 | 5980 | if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) { |
| 5848 | 5981 | return self.fail("stack offset too large", .{}); |
| 5849 | 5982 | } |
| 5850 | 5983 | _ = try self.addInst(.{ |
| 5851 | 5984 | .tag = .lea, |
| 5852 | | .ops = (Mir.Ops{ |
| 5985 | .ops = (Mir.Ops(Register, Register){ |
| 5853 | 5986 | .reg1 = registerAlias(reg, abi_size), |
| 5854 | 5987 | .reg2 = .rbp, |
| 5855 | 5988 | }).encode(), |
| ... | ... | @@ -5889,7 +6022,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5889 | 6022 | }; |
| 5890 | 6023 | _ = try self.addInst(.{ |
| 5891 | 6024 | .tag = tag, |
| 5892 | | .ops = (Mir.Ops{ |
| 6025 | .ops = (Mir.Ops(Register, Register){ |
| 5893 | 6026 | .reg1 = reg.to8(), |
| 5894 | 6027 | .flags = flags, |
| 5895 | 6028 | }).encode(), |
| ... | ... | @@ -5902,7 +6035,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5902 | 6035 | if (x == 0) { |
| 5903 | 6036 | _ = try self.addInst(.{ |
| 5904 | 6037 | .tag = .xor, |
| 5905 | | .ops = (Mir.Ops{ |
| 6038 | .ops = (Mir.Ops(Register, Register){ |
| 5906 | 6039 | .reg1 = reg.to32(), |
| 5907 | 6040 | .reg2 = reg.to32(), |
| 5908 | 6041 | }).encode(), |
| ... | ... | @@ -5914,7 +6047,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5914 | 6047 | // Next best case: if we set the lower four bytes, the upper four will be zeroed. |
| 5915 | 6048 | _ = try self.addInst(.{ |
| 5916 | 6049 | .tag = .mov, |
| 5917 | | .ops = (Mir.Ops{ |
| 6050 | .ops = (Mir.Ops(Register, Register){ |
| 5918 | 6051 | .reg1 = registerAlias(reg, abi_size), |
| 5919 | 6052 | }).encode(), |
| 5920 | 6053 | .data = .{ .imm = @truncate(u32, x) }, |
| ... | ... | @@ -5931,7 +6064,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5931 | 6064 | const payload = try self.addExtra(Mir.Imm64.encode(x)); |
| 5932 | 6065 | _ = try self.addInst(.{ |
| 5933 | 6066 | .tag = .movabs, |
| 5934 | | .ops = (Mir.Ops{ |
| 6067 | .ops = (Mir.Ops(Register, Register){ |
| 5935 | 6068 | .reg1 = reg.to64(), |
| 5936 | 6069 | }).encode(), |
| 5937 | 6070 | .data = .{ .payload = payload }, |
| ... | ... | @@ -5948,7 +6081,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5948 | 6081 | if (abi_size > 4) break :blk; |
| 5949 | 6082 | _ = try self.addInst(.{ |
| 5950 | 6083 | .tag = .mov_sign_extend, |
| 5951 | | .ops = (Mir.Ops{ |
| 6084 | .ops = (Mir.Ops(Register, Register){ |
| 5952 | 6085 | .reg1 = reg.to64(), |
| 5953 | 6086 | .reg2 = registerAlias(src_reg, abi_size), |
| 5954 | 6087 | }).encode(), |
| ... | ... | @@ -5959,7 +6092,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5959 | 6092 | if (abi_size > 2) break :blk; |
| 5960 | 6093 | _ = try self.addInst(.{ |
| 5961 | 6094 | .tag = .mov_zero_extend, |
| 5962 | | .ops = (Mir.Ops{ |
| 6095 | .ops = (Mir.Ops(Register, Register){ |
| 5963 | 6096 | .reg1 = reg.to64(), |
| 5964 | 6097 | .reg2 = registerAlias(src_reg, abi_size), |
| 5965 | 6098 | }).encode(), |
| ... | ... | @@ -5972,7 +6105,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5972 | 6105 | |
| 5973 | 6106 | _ = try self.addInst(.{ |
| 5974 | 6107 | .tag = .mov, |
| 5975 | | .ops = (Mir.Ops{ |
| 6108 | .ops = (Mir.Ops(Register, Register){ |
| 5976 | 6109 | .reg1 = registerAlias(reg, abi_size), |
| 5977 | 6110 | .reg2 = registerAlias(src_reg, abi_size), |
| 5978 | 6111 | }).encode(), |
| ... | ... | @@ -5985,7 +6118,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5985 | 6118 | try self.loadMemPtrIntoRegister(reg, Type.usize, mcv); |
| 5986 | 6119 | _ = try self.addInst(.{ |
| 5987 | 6120 | .tag = .mov, |
| 5988 | | .ops = (Mir.Ops{ |
| 6121 | .ops = (Mir.Ops(Register, Register){ |
| 5989 | 6122 | .reg1 = registerAlias(reg, abi_size), |
| 5990 | 6123 | .reg2 = reg.to64(), |
| 5991 | 6124 | .flags = 0b01, |
| ... | ... | @@ -5998,7 +6131,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5998 | 6131 | // mov reg, [ds:imm32] |
| 5999 | 6132 | _ = try self.addInst(.{ |
| 6000 | 6133 | .tag = .mov, |
| 6001 | | .ops = (Mir.Ops{ |
| 6134 | .ops = (Mir.Ops(Register, Register){ |
| 6002 | 6135 | .reg1 = registerAlias(reg, abi_size), |
| 6003 | 6136 | .flags = 0b01, |
| 6004 | 6137 | }).encode(), |
| ... | ... | @@ -6012,7 +6145,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6012 | 6145 | const payload = try self.addExtra(Mir.Imm64.encode(x)); |
| 6013 | 6146 | _ = try self.addInst(.{ |
| 6014 | 6147 | .tag = .movabs, |
| 6015 | | .ops = (Mir.Ops{ |
| 6148 | .ops = (Mir.Ops(Register, Register){ |
| 6016 | 6149 | .reg1 = .rax, |
| 6017 | 6150 | .flags = 0b01, // imm64 will become moffs64 |
| 6018 | 6151 | }).encode(), |
| ... | ... | @@ -6025,7 +6158,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6025 | 6158 | // mov reg, [reg + 0x0] |
| 6026 | 6159 | _ = try self.addInst(.{ |
| 6027 | 6160 | .tag = .mov, |
| 6028 | | .ops = (Mir.Ops{ |
| 6161 | .ops = (Mir.Ops(Register, Register){ |
| 6029 | 6162 | .reg1 = registerAlias(reg, abi_size), |
| 6030 | 6163 | .reg2 = reg.to64(), |
| 6031 | 6164 | .flags = 0b01, |
| ... | ... | @@ -6051,7 +6184,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6051 | 6184 | }; |
| 6052 | 6185 | _ = try self.addInst(.{ |
| 6053 | 6186 | .tag = .mov_sign_extend, |
| 6054 | | .ops = (Mir.Ops{ |
| 6187 | .ops = (Mir.Ops(Register, Register){ |
| 6055 | 6188 | .reg1 = reg.to64(), |
| 6056 | 6189 | .reg2 = .rbp, |
| 6057 | 6190 | .flags = flags, |
| ... | ... | @@ -6067,7 +6200,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6067 | 6200 | }; |
| 6068 | 6201 | _ = try self.addInst(.{ |
| 6069 | 6202 | .tag = .mov_zero_extend, |
| 6070 | | .ops = (Mir.Ops{ |
| 6203 | .ops = (Mir.Ops(Register, Register){ |
| 6071 | 6204 | .reg1 = reg.to64(), |
| 6072 | 6205 | .reg2 = .rbp, |
| 6073 | 6206 | .flags = flags, |
| ... | ... | @@ -6081,7 +6214,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6081 | 6214 | |
| 6082 | 6215 | _ = try self.addInst(.{ |
| 6083 | 6216 | .tag = .mov, |
| 6084 | | .ops = (Mir.Ops{ |
| 6217 | .ops = (Mir.Ops(Register, Register){ |
| 6085 | 6218 | .reg1 = registerAlias(reg, abi_size), |
| 6086 | 6219 | .reg2 = .rbp, |
| 6087 | 6220 | .flags = 0b01, |
| ... | ... | @@ -6152,7 +6285,7 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 6152 | 6285 | }; |
| 6153 | 6286 | _ = try self.addInst(.{ |
| 6154 | 6287 | .tag = .fld, |
| 6155 | | .ops = (Mir.Ops{ |
| 6288 | .ops = (Mir.Ops(Register, Register){ |
| 6156 | 6289 | .flags = switch (src_ty.abiSize(self.target.*)) { |
| 6157 | 6290 | 4 => 0b01, |
| 6158 | 6291 | 8 => 0b10, |
| ... | ... | @@ -6167,7 +6300,7 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 6167 | 6300 | const stack_dst = try self.allocRegOrMem(inst, false); |
| 6168 | 6301 | _ = try self.addInst(.{ |
| 6169 | 6302 | .tag = .fisttp, |
| 6170 | | .ops = (Mir.Ops{ |
| 6303 | .ops = (Mir.Ops(Register, Register){ |
| 6171 | 6304 | .flags = switch (dst_ty.abiSize(self.target.*)) { |
| 6172 | 6305 | 1...2 => 0b00, |
| 6173 | 6306 | 3...4 => 0b01, |
| ... | ... | @@ -6271,7 +6404,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 6271 | 6404 | try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr); |
| 6272 | 6405 | _ = try self.addInst(.{ |
| 6273 | 6406 | .tag = .mov, |
| 6274 | | .ops = (Mir.Ops{ |
| 6407 | .ops = (Mir.Ops(Register, Register){ |
| 6275 | 6408 | .reg1 = reg, |
| 6276 | 6409 | .reg2 = reg, |
| 6277 | 6410 | .flags = 0b01, |
| ... | ... | @@ -6840,7 +6973,20 @@ fn registerAlias(reg: Register, size_bytes: u32) Register { |
| 6840 | 6973 | } else if (size_bytes <= 8) { |
| 6841 | 6974 | return reg.to64(); |
| 6842 | 6975 | } else { |
| 6843 | | unreachable; // TODO handle floating-point registers |
| 6976 | unreachable; |
| 6977 | } |
| 6978 | } |
| 6979 | |
| 6980 | /// Returns AVX register wide enough to hold at least `size_bytes`. |
| 6981 | fn avxRegisterAlias(reg: AvxRegister, size_bytes: u32) AvxRegister { |
| 6982 | if (size_bytes == 0) { |
| 6983 | unreachable; // should be comptime known |
| 6984 | } else if (size_bytes <= 16) { |
| 6985 | return reg.to128(); |
| 6986 | } else if (size_bytes <= 32) { |
| 6987 | return reg.to256(); |
| 6988 | } else { |
| 6989 | unreachable; |
| 6844 | 6990 | } |
| 6845 | 6991 | } |
| 6846 | 6992 | |