x64: implement array_elem_val when array is stored in memory

This commit is contained in:
Jakub Konka 2022-02-17 18:10:02 +01:00
parent abfaf8382b
commit 97c25fb8d0
2 changed files with 50 additions and 64 deletions

View File

@ -1604,6 +1604,12 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
.stack_offset => |off| {
break :inner off;
},
.memory,
.got_load,
.direct_load,
=> {
break :blk try self.loadMemPtrIntoRegister(Type.usize, array);
},
else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
}
};
@ -1845,6 +1851,42 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
fn loadMemPtrIntoRegister(self: *Self, ptr_ty: Type, ptr: MCValue) InnerError!Register {
switch (ptr) {
.got_load,
.direct_load,
=> |sym_index| {
const flags: u2 = switch (ptr) {
.got_load => 0b00,
.direct_load => 0b01,
else => unreachable,
};
const reg = try self.register_manager.allocReg(null);
_ = try self.addInst(.{
.tag = .lea_pie,
.ops = (Mir.Ops{
.reg1 = reg.to64(),
.flags = flags,
}).encode(),
.data = .{
.load_reloc = .{
.atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
.sym_index = sym_index,
},
},
});
return reg.to64();
},
.memory => |addr| {
// TODO: in case the address fits in an imm32 we can use [ds:imm32]
// instead of wasting an instruction copying the address to a register
const reg = try self.copyToTmpRegister(ptr_ty, .{ .immediate = addr });
return reg.to64();
},
else => unreachable,
}
}
fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {
_ = ptr_ty;
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
value.freezeIfRegister(&self.register_manager);
defer value.unfreezeIfRegister(&self.register_manager);
const addr_reg: Register = blk: {
switch (ptr) {
.got_load,
.direct_load,
=> |sym_index| {
const flags: u2 = switch (ptr) {
.got_load => 0b00,
.direct_load => 0b01,
else => unreachable,
};
const addr_reg = try self.register_manager.allocReg(null);
_ = try self.addInst(.{
.tag = .lea_pie,
.ops = (Mir.Ops{
.reg1 = addr_reg.to64(),
.flags = flags,
}).encode(),
.data = .{
.load_reloc = .{
.atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
.sym_index = sym_index,
},
},
});
break :blk addr_reg;
},
.memory => |addr| {
// TODO: in case the address fits in an imm32 we can use [ds:imm32]
// instead of wasting an instruction copying the address to a register
const addr_reg = try self.copyToTmpRegister(ptr_ty, .{ .immediate = addr });
break :blk addr_reg;
},
else => unreachable,
}
};
const addr_reg = try self.loadMemPtrIntoRegister(ptr_ty, ptr);
// to get the actual address of the value we want to modify we have to go through the GOT
// mov reg, [reg]
@ -3831,33 +3839,11 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, stack_reg: Register, ty: Type
const addr_reg: Register = blk: {
switch (val) {
.memory => |addr| {
const reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = addr });
break :blk reg;
},
.memory,
.direct_load,
.got_load,
=> |sym_index| {
const flags: u2 = switch (val) {
.got_load => 0b00,
.direct_load => 0b01,
else => unreachable,
};
const addr_reg = (try self.register_manager.allocReg(null)).to64();
_ = try self.addInst(.{
.tag = .lea_pie,
.ops = (Mir.Ops{
.reg1 = addr_reg,
.flags = flags,
}).encode(),
.data = .{
.load_reloc = .{
.atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
.sym_index = sym_index,
},
},
});
break :blk addr_reg;
=> {
break :blk try self.loadMemPtrIntoRegister(Type.usize, val);
},
.stack_offset => |off| {
const addr_reg = (try self.register_manager.allocReg(null)).to64();

View File

@ -153,7 +153,7 @@ test "void arrays" {
test "nested arrays" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
const array_of_strings = [_][]const u8{ "hello", "this", "is", "my", "thing" };
for (array_of_strings) |s, i| {
@ -525,8 +525,8 @@ test "zero-sized array with recursive type definition" {
test "type coercion of anon struct literal to array" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
const S = struct {
const U = union {
@ -543,8 +543,8 @@ test "type coercion of anon struct literal to array" {
try expect(arr1[1] == 56);
try expect(arr1[2] == 54);
if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
if (@import("builtin").zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
var x2: U = .{ .a = 42 };
const t2 = .{ x2, .{ .b = true }, .{ .c = "hello" } };