authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-28 19:19:10+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-28 23:20:05+01:00
logdecc90e0e76bb657bb670c6fa74db1f76248be4b
tree267c0f978cfa4a0a22e4232ab4eba27e4ce79cb2
parent12cdb36c5ba1fd9dfa5985d36a2f5955528c2de7

x64: clean up loadMemPtrIntoRegister abstraction


2 files changed, 80 insertions(+), 83 deletions(-)

src/arch/x86_64/CodeGen.zig+80-81
...@@ -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});
20342034
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 }
20712073
2072 // TODO we could allocate register here, but need to expect addr register and potentially2074 // 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}
23752377
2376fn loadMemPtrIntoRegister(self: *Self, ptr_ty: Type, ptr: MCValue) InnerError!Register {2378fn 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 register2404 // 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);
25282531
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);
25302534
2531 // to get the actual address of the value we want to modify we have to go through the GOT2535 // 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});
46804684
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 };
47184717
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});
test/behavior/union.zig-2
...@@ -401,7 +401,6 @@ test "tagged union with no payloads" {...@@ -401,7 +401,6 @@ test "tagged union with no payloads" {
401}401}
402402
403test "union with only 1 field casted to its enum type" {403test "union with only 1 field casted to its enum type" {
404 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
405 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
406 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;405 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
407406
...@@ -841,7 +840,6 @@ test "@unionInit can modify a union type" {...@@ -841,7 +840,6 @@ test "@unionInit can modify a union type" {
841}840}
842841
843test "@unionInit can modify a pointer value" {842test "@unionInit can modify a pointer value" {
844 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
845 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO843 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
846 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO844 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
847845