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