authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-17 18:10:02+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-18 09:14:15+01:00
log97c25fb8d049ebcced9f29241516c51e480fb8a0
treee86b505de42686b87a05959abbf624f9682fbc7a
parentabfaf8382b58d8bdfa029b74205d385cbc73d78e

x64: implement array_elem_val when array is stored in memory


2 files changed, 50 insertions(+), 64 deletions(-)

src/arch/x86_64/CodeGen.zig+46-60
......@@ -1604,6 +1604,12 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
16041604 .stack_offset => |off| {
16051605 break :inner off;
16061606 },
1607 .memory,
1608 .got_load,
1609 .direct_load,
1610 => {
1611 break :blk try self.loadMemPtrIntoRegister(Type.usize, array);
1612 },
16071613 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
16081614 }
16091615 };
......@@ -1845,6 +1851,42 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
18451851 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
18461852}
18471853
1854fn loadMemPtrIntoRegister(self: *Self, ptr_ty: Type, ptr: MCValue) InnerError!Register {
1855 switch (ptr) {
1856 .got_load,
1857 .direct_load,
1858 => |sym_index| {
1859 const flags: u2 = switch (ptr) {
1860 .got_load => 0b00,
1861 .direct_load => 0b01,
1862 else => unreachable,
1863 };
1864 const reg = try self.register_manager.allocReg(null);
1865 _ = try self.addInst(.{
1866 .tag = .lea_pie,
1867 .ops = (Mir.Ops{
1868 .reg1 = reg.to64(),
1869 .flags = flags,
1870 }).encode(),
1871 .data = .{
1872 .load_reloc = .{
1873 .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
1874 .sym_index = sym_index,
1875 },
1876 },
1877 });
1878 return reg.to64();
1879 },
1880 .memory => |addr| {
1881 // TODO: in case the address fits in an imm32 we can use [ds:imm32]
1882 // instead of wasting an instruction copying the address to a register
1883 const reg = try self.copyToTmpRegister(ptr_ty, .{ .immediate = addr });
1884 return reg.to64();
1885 },
1886 else => unreachable,
1887 }
1888}
1889
18481890fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {
18491891 _ = ptr_ty;
18501892 const abi_size = value_ty.abiSize(self.target.*);
......@@ -1955,41 +1997,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
19551997 value.freezeIfRegister(&self.register_manager);
19561998 defer value.unfreezeIfRegister(&self.register_manager);
19571999
1958 const addr_reg: Register = blk: {
1959 switch (ptr) {
1960 .got_load,
1961 .direct_load,
1962 => |sym_index| {
1963 const flags: u2 = switch (ptr) {
1964 .got_load => 0b00,
1965 .direct_load => 0b01,
1966 else => unreachable,
1967 };
1968 const addr_reg = try self.register_manager.allocReg(null);
1969 _ = try self.addInst(.{
1970 .tag = .lea_pie,
1971 .ops = (Mir.Ops{
1972 .reg1 = addr_reg.to64(),
1973 .flags = flags,
1974 }).encode(),
1975 .data = .{
1976 .load_reloc = .{
1977 .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
1978 .sym_index = sym_index,
1979 },
1980 },
1981 });
1982 break :blk addr_reg;
1983 },
1984 .memory => |addr| {
1985 // TODO: in case the address fits in an imm32 we can use [ds:imm32]
1986 // instead of wasting an instruction copying the address to a register
1987 const addr_reg = try self.copyToTmpRegister(ptr_ty, .{ .immediate = addr });
1988 break :blk addr_reg;
1989 },
1990 else => unreachable,
1991 }
1992 };
2000 const addr_reg = try self.loadMemPtrIntoRegister(ptr_ty, ptr);
19932001
19942002 // to get the actual address of the value we want to modify we have to go through the GOT
19952003 // mov reg, [reg]
......@@ -3831,33 +3839,11 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, stack_reg: Register, ty: Type
38313839
38323840 const addr_reg: Register = blk: {
38333841 switch (val) {
3834 .memory => |addr| {
3835 const reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = addr });
3836 break :blk reg;
3837 },
3842 .memory,
38383843 .direct_load,
38393844 .got_load,
3840 => |sym_index| {
3841 const flags: u2 = switch (val) {
3842 .got_load => 0b00,
3843 .direct_load => 0b01,
3844 else => unreachable,
3845 };
3846 const addr_reg = (try self.register_manager.allocReg(null)).to64();
3847 _ = try self.addInst(.{
3848 .tag = .lea_pie,
3849 .ops = (Mir.Ops{
3850 .reg1 = addr_reg,
3851 .flags = flags,
3852 }).encode(),
3853 .data = .{
3854 .load_reloc = .{
3855 .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
3856 .sym_index = sym_index,
3857 },
3858 },
3859 });
3860 break :blk addr_reg;
3845 => {
3846 break :blk try self.loadMemPtrIntoRegister(Type.usize, val);
38613847 },
38623848 .stack_offset => |off| {
38633849 const addr_reg = (try self.register_manager.allocReg(null)).to64();
test/behavior/array.zig+4-4
......@@ -153,7 +153,7 @@ test "void arrays" {
153153
154154test "nested arrays" {
155155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
156 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
156 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
157157
158158 const array_of_strings = [_][]const u8{ "hello", "this", "is", "my", "thing" };
159159 for (array_of_strings) |s, i| {
......@@ -525,8 +525,8 @@ test "zero-sized array with recursive type definition" {
525525test "type coercion of anon struct literal to array" {
526526 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
527527 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
528 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
529528 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
529 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
530530
531531 const S = struct {
532532 const U = union {
......@@ -543,8 +543,8 @@ test "type coercion of anon struct literal to array" {
543543 try expect(arr1[1] == 56);
544544 try expect(arr1[2] == 54);
545545
546 if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
547 if (@import("builtin").zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
546 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
547 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
548548
549549 var x2: U = .{ .a = 42 };
550550 const t2 = .{ x2, .{ .b = true }, .{ .c = "hello" } };