| ... | @@ -2032,42 +2032,44 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2032,42 +2032,44 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2032 | self.register_manager.freezeRegs(&.{offset_reg}); | 2032 | self.register_manager.freezeRegs(&.{offset_reg}); |
| 2033 | defer self.register_manager.unfreezeRegs(&.{offset_reg}); | 2033 | defer self.register_manager.unfreezeRegs(&.{offset_reg}); |
| 2034 | | 2034 | |
| 2035 | const addr_reg = blk: { | 2035 | const addr_reg = try self.register_manager.allocReg(null); |
| 2036 | const off = inner: { | 2036 | switch (array) { |
| 2037 | switch (array) { | 2037 | .register => { |
| 2038 | .register => { | 2038 | const off = @intCast(i32, try self.allocMem( |
| 2039 | const off = @intCast(i32, try self.allocMem( | 2039 | inst, |
| 2040 | inst, | 2040 | @intCast(u32, array_ty.abiSize(self.target.*)), |
| 2041 | @intCast(u32, array_ty.abiSize(self.target.*)), | 2041 | array_ty.abiAlignment(self.target.*), |
| 2042 | array_ty.abiAlignment(self.target.*), | 2042 | )); |
| 2043 | )); | 2043 | try self.genSetStack(array_ty, off, array, .{}); |
| 2044 | try self.genSetStack(array_ty, off, array, .{}); | 2044 | // lea reg, [rbp] |
| 2045 | break :inner off; | 2045 | _ = try self.addInst(.{ |
| 2046 | }, | 2046 | .tag = .lea, |
| 2047 | .stack_offset => |off| { | 2047 | .ops = (Mir.Ops{ |
| 2048 | break :inner off; | 2048 | .reg1 = addr_reg.to64(), |
| 2049 | }, | 2049 | .reg2 = .rbp, |
| 2050 | .memory, | 2050 | }).encode(), |
| 2051 | .got_load, | 2051 | .data = .{ .imm = @bitCast(u32, -off) }, |
| 2052 | .direct_load, | 2052 | }); |
| 2053 | => { | 2053 | }, |
| 2054 | break :blk try self.loadMemPtrIntoRegister(Type.usize, array); | 2054 | .stack_offset => |off| { |
| 2055 | }, | 2055 | // lea reg, [rbp] |
| 2056 | else => return self.fail("TODO implement array_elem_val when array is {}", .{array}), | 2056 | _ = try self.addInst(.{ |
| 2057 | } | 2057 | .tag = .lea, |
| 2058 | }; | 2058 | .ops = (Mir.Ops{ |
| 2059 | const addr_reg = try self.register_manager.allocReg(null); | 2059 | .reg1 = addr_reg.to64(), |
| 2060 | // lea reg, [rbp] | 2060 | .reg2 = .rbp, |
| 2061 | _ = try self.addInst(.{ | 2061 | }).encode(), |
| 2062 | .tag = .lea, | 2062 | .data = .{ .imm = @bitCast(u32, -off) }, |
| 2063 | .ops = (Mir.Ops{ | 2063 | }); |
| 2064 | .reg1 = addr_reg.to64(), | 2064 | }, |
| 2065 | .reg2 = .rbp, | 2065 | .memory, |
| 2066 | }).encode(), | 2066 | .got_load, |
| 2067 | .data = .{ .imm = @bitCast(u32, -off) }, | 2067 | .direct_load, |
| 2068 | }); | 2068 | => { |
| 2069 | break :blk addr_reg.to64(); | 2069 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, array); |
| 2070 | }; | 2070 | }, |
| | 2071 | else => return self.fail("TODO implement array_elem_val when array is {}", .{array}), |
| | 2072 | } |
| 2071 | | 2073 | |
| 2072 | // TODO we could allocate register here, but need to expect addr register and potentially | 2074 | // TODO we could allocate register here, but need to expect addr register and potentially |
| 2073 | // offset register. | 2075 | // offset register. |
| ... | @@ -2373,7 +2375,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2373,7 +2375,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 2373 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 2375 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2374 | } | 2376 | } |
| 2375 | | 2377 | |
| 2376 | fn loadMemPtrIntoRegister(self: *Self, ptr_ty: Type, ptr: MCValue) InnerError!Register { | 2378 | fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue) InnerError!void { |
| 2377 | switch (ptr) { | 2379 | switch (ptr) { |
| 2378 | .got_load, | 2380 | .got_load, |
| 2379 | .direct_load, | 2381 | .direct_load, |
| ... | @@ -2383,11 +2385,10 @@ fn loadMemPtrIntoRegister(self: *Self, ptr_ty: Type, ptr: MCValue) InnerError!Re | ... | @@ -2383,11 +2385,10 @@ fn loadMemPtrIntoRegister(self: *Self, ptr_ty: Type, ptr: MCValue) InnerError!Re |
| 2383 | .direct_load => 0b01, | 2385 | .direct_load => 0b01, |
| 2384 | else => unreachable, | 2386 | else => unreachable, |
| 2385 | }; | 2387 | }; |
| 2386 | const reg = try self.register_manager.allocReg(null); | | |
| 2387 | _ = try self.addInst(.{ | 2388 | _ = try self.addInst(.{ |
| 2388 | .tag = .lea_pie, | 2389 | .tag = .lea_pie, |
| 2389 | .ops = (Mir.Ops{ | 2390 | .ops = (Mir.Ops{ |
| 2390 | .reg1 = reg.to64(), | 2391 | .reg1 = registerAlias(reg, @intCast(u32, ptr_ty.abiSize(self.target.*))), |
| 2391 | .flags = flags, | 2392 | .flags = flags, |
| 2392 | }).encode(), | 2393 | }).encode(), |
| 2393 | .data = .{ | 2394 | .data = .{ |
| ... | @@ -2397,13 +2398,11 @@ fn loadMemPtrIntoRegister(self: *Self, ptr_ty: Type, ptr: MCValue) InnerError!Re | ... | @@ -2397,13 +2398,11 @@ fn loadMemPtrIntoRegister(self: *Self, ptr_ty: Type, ptr: MCValue) InnerError!Re |
| 2397 | }, | 2398 | }, |
| 2398 | }, | 2399 | }, |
| 2399 | }); | 2400 | }); |
| 2400 | return reg.to64(); | | |
| 2401 | }, | 2401 | }, |
| 2402 | .memory => |addr| { | 2402 | .memory => |addr| { |
| 2403 | // TODO: in case the address fits in an imm32 we can use [ds:imm32] | 2403 | // TODO: in case the address fits in an imm32 we can use [ds:imm32] |
| 2404 | // instead of wasting an instruction copying the address to a register | 2404 | // instead of wasting an instruction copying the address to a register |
| 2405 | const reg = try self.copyToTmpRegister(ptr_ty, .{ .immediate = addr }); | 2405 | try self.genSetReg(ptr_ty, reg, .{ .immediate = addr }); |
| 2406 | return reg.to64(); | | |
| 2407 | }, | 2406 | }, |
| 2408 | else => unreachable, | 2407 | else => unreachable, |
| 2409 | } | 2408 | } |
| ... | @@ -2503,7 +2502,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2503,7 +2502,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2503 | .data = .{ .imm = 0 }, | 2502 | .data = .{ .imm = 0 }, |
| 2504 | }); | 2503 | }); |
| 2505 | }, | 2504 | }, |
| 2506 | .stack_offset => { | 2505 | .got_load, |
| | 2506 | .direct_load, |
| | 2507 | .memory, |
| | 2508 | .stack_offset, |
| | 2509 | => { |
| 2507 | if (abi_size <= 8) { | 2510 | if (abi_size <= 8) { |
| 2508 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); | 2511 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); |
| 2509 | return self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); | 2512 | return self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); |
| ... | @@ -2526,7 +2529,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2526,7 +2529,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2526 | value.freezeIfRegister(&self.register_manager); | 2529 | value.freezeIfRegister(&self.register_manager); |
| 2527 | defer value.unfreezeIfRegister(&self.register_manager); | 2530 | defer value.unfreezeIfRegister(&self.register_manager); |
| 2528 | | 2531 | |
| 2529 | const addr_reg = try self.loadMemPtrIntoRegister(ptr_ty, ptr); | 2532 | const addr_reg = try self.register_manager.allocReg(null); |
| | 2533 | try self.loadMemPtrIntoRegister(addr_reg, ptr_ty, ptr); |
| 2530 | | 2534 | |
| 2531 | // to get the actual address of the value we want to modify we have to go through the GOT | 2535 | // to get the actual address of the value we want to modify we have to go through the GOT |
| 2532 | // mov reg, [reg] | 2536 | // mov reg, [reg] |
| ... | @@ -4678,43 +4682,38 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: | ... | @@ -4678,43 +4682,38 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: |
| 4678 | if (opts.dest_stack_base) |reg| self.register_manager.freezeRegs(&.{reg}); | 4682 | if (opts.dest_stack_base) |reg| self.register_manager.freezeRegs(&.{reg}); |
| 4679 | defer if (opts.dest_stack_base) |reg| self.register_manager.unfreezeRegs(&.{reg}); | 4683 | defer if (opts.dest_stack_base) |reg| self.register_manager.unfreezeRegs(&.{reg}); |
| 4680 | | 4684 | |
| 4681 | const addr_reg: Register = blk: { | 4685 | const addr_reg = try self.register_manager.allocReg(null); |
| 4682 | switch (val) { | 4686 | switch (val) { |
| 4683 | .memory, | 4687 | .memory, |
| 4684 | .direct_load, | 4688 | .direct_load, |
| 4685 | .got_load, | 4689 | .got_load, |
| 4686 | => { | 4690 | => { |
| 4687 | break :blk try self.loadMemPtrIntoRegister(Type.usize, val); | 4691 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, val); |
| 4688 | }, | 4692 | }, |
| 4689 | .ptr_stack_offset, .stack_offset => |off| { | 4693 | .ptr_stack_offset, .stack_offset => |off| { |
| 4690 | const addr_reg = (try self.register_manager.allocReg(null)).to64(); | 4694 | _ = try self.addInst(.{ |
| 4691 | _ = try self.addInst(.{ | 4695 | .tag = .lea, |
| 4692 | .tag = .lea, | 4696 | .ops = (Mir.Ops{ |
| 4693 | .ops = (Mir.Ops{ | 4697 | .reg1 = addr_reg.to64(), |
| 4694 | .reg1 = addr_reg, | 4698 | .reg2 = opts.source_stack_base orelse .rbp, |
| 4695 | .reg2 = opts.source_stack_base orelse .rbp, | 4699 | }).encode(), |
| 4696 | }).encode(), | 4700 | .data = .{ .imm = @bitCast(u32, -off) }, |
| 4697 | .data = .{ .imm = @bitCast(u32, -off) }, | 4701 | }); |
| 4698 | }); | 4702 | }, |
| 4699 | break :blk addr_reg; | 4703 | .register => |reg| { |
| 4700 | }, | 4704 | _ = try self.addInst(.{ |
| 4701 | .register => |reg| { | 4705 | .tag = .mov, |
| 4702 | const addr_reg = try self.register_manager.allocReg(null); | 4706 | .ops = (Mir.Ops{ |
| 4703 | _ = try self.addInst(.{ | 4707 | .reg1 = registerAlias(addr_reg, @divExact(reg.size(), 8)), |
| 4704 | .tag = .mov, | 4708 | .reg2 = reg, |
| 4705 | .ops = (Mir.Ops{ | 4709 | }).encode(), |
| 4706 | .reg1 = registerAlias(addr_reg, @divExact(reg.size(), 8)), | 4710 | .data = undefined, |
| 4707 | .reg2 = reg, | 4711 | }); |
| 4708 | }).encode(), | 4712 | }, |
| 4709 | .data = undefined, | 4713 | else => { |
| 4710 | }); | 4714 | return self.fail("TODO implement memcpy for setting stack from {}", .{val}); |
| 4711 | break :blk addr_reg.to64(); | 4715 | }, |
| 4712 | }, | 4716 | } |
| 4713 | else => { | | |
| 4714 | return self.fail("TODO implement memcpy for setting stack from {}", .{val}); | | |
| 4715 | }, | | |
| 4716 | } | | |
| 4717 | }; | | |
| 4718 | | 4717 | |
| 4719 | self.register_manager.freezeRegs(&.{addr_reg}); | 4718 | self.register_manager.freezeRegs(&.{addr_reg}); |
| 4720 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); | 4719 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |