stage2 AArch64: more support for MCValue.got_load and direct_load

This commit is contained in:
joachimschmidt557 2022-02-23 21:32:25 +01:00
parent 4683f94463
commit f91fe9afb9
No known key found for this signature in database
GPG Key ID: E0B575BE2884ACC5
9 changed files with 73 additions and 41 deletions

View File

@ -1717,6 +1717,8 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind
fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {
const elem_ty = ptr_ty.elemType();
const elem_size = elem_ty.abiSize(self.target.*);
switch (ptr) {
.none => unreachable,
.undef => unreachable,
@ -1736,17 +1738,16 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
self.register_manager.freezeRegs(&.{addr_reg});
defer self.register_manager.unfreezeRegs(&.{addr_reg});
const abi_size = elem_ty.abiSize(self.target.*);
switch (dst_mcv) {
.dead => unreachable,
.undef => unreachable,
.compare_flags_signed, .compare_flags_unsigned => unreachable,
.embedded_in_code => unreachable,
.register => |dst_reg| {
try self.genLdrRegister(dst_reg, addr_reg, abi_size);
try self.genLdrRegister(dst_reg, addr_reg, elem_size);
},
.stack_offset => |off| {
if (abi_size <= 8) {
if (elem_size <= 8) {
const tmp_reg = try self.register_manager.allocReg(null);
self.register_manager.freezeRegs(&.{tmp_reg});
defer self.register_manager.unfreezeRegs(&.{tmp_reg});
@ -1766,17 +1767,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
const tmp_reg = regs[3];
// sub dst_reg, fp, #off
const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
const adj_off = off + elem_size;
const offset = math.cast(u12, adj_off) catch return self.fail("TODO load: larger stack offsets", .{});
_ = try self.addInst(.{
.tag = .sub_immediate,
.data = .{ .rr_imm12_sh = .{
.rd = dst_reg,
.rn = .x29,
.imm12 = offset,
} },
});
try self.genSetReg(ptr_ty, dst_reg, .{ .ptr_stack_offset = off });
// mov len, #elem_size
try self.genSetReg(Type.usize, len_reg, .{ .immediate = elem_size });
@ -2046,14 +2037,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
},
.memory,
.stack_offset,
=> {
const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);
try self.store(.{ .register = addr_reg }, value, ptr_ty, value_ty);
},
.got_load,
.direct_load,
=> {
return self.fail("TODO implement storing to {}", .{ptr});
const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr);
try self.store(.{ .register = addr_reg }, value, ptr_ty, value_ty);
},
}
}
@ -3142,10 +3130,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
},
.got_load,
.direct_load,
=> |sym_index| {
_ = sym_index;
return self.fail("TODO implement set stack variable from {}", .{mcv});
},
.memory,
.stack_offset,
=> {
@ -3187,6 +3171,25 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
});
},
.memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }),
.got_load,
.direct_load,
=> |sym_index| {
const tag: Mir.Inst.Tag = switch (mcv) {
.got_load => .load_memory_ptr_got,
.direct_load => .load_memory_ptr_direct,
else => unreachable,
};
_ = try self.addInst(.{
.tag = tag,
.data = .{
.payload = try self.addExtra(Mir.LoadMemoryPie{
.register = @enumToInt(src_reg),
.atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index,
.sym_index = sym_index,
}),
},
});
},
else => unreachable,
}

View File

@ -110,6 +110,8 @@ pub fn emitMir(
.load_memory_got => try emit.mirLoadMemoryPie(inst),
.load_memory_direct => try emit.mirLoadMemoryPie(inst),
.load_memory_ptr_got => try emit.mirLoadMemoryPie(inst),
.load_memory_ptr_direct => try emit.mirLoadMemoryPie(inst),
.ldp => try emit.mirLoadStoreRegisterPair(inst),
.stp => try emit.mirLoadStoreRegisterPair(inst),
@ -208,6 +210,8 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {
switch (tag) {
.load_memory_got,
.load_memory_direct,
.load_memory_ptr_got,
.load_memory_ptr_direct,
=> return 2 * 4,
.pop_regs, .push_regs => {
const reg_list = emit.mir.instructions.items(.data)[inst].reg_list;
@ -655,12 +659,25 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
const offset = @intCast(u32, emit.code.items.len);
try emit.writeInstruction(Instruction.adrp(reg, 0));
// ldr reg, reg, offset
try emit.writeInstruction(Instruction.ldr(
reg,
reg,
Instruction.LoadStoreOffset.imm(0),
));
switch (tag) {
.load_memory_got,
.load_memory_direct,
=> {
// ldr reg, reg, offset
try emit.writeInstruction(Instruction.ldr(
reg,
reg,
Instruction.LoadStoreOffset.imm(0),
));
},
.load_memory_ptr_got,
.load_memory_ptr_direct,
=> {
// add reg, reg, offset
try emit.writeInstruction(Instruction.add(reg, reg, 0, false));
},
else => unreachable,
}
if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
const atom = macho_file.atom_by_index_table.get(data.atom_index).?;
@ -673,8 +690,12 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
.pcrel = true,
.length = 2,
.@"type" = switch (tag) {
.load_memory_got => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21),
.load_memory_direct => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGE21),
.load_memory_got,
.load_memory_ptr_got,
=> @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21),
.load_memory_direct,
.load_memory_ptr_direct,
=> @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGE21),
else => unreachable,
},
});
@ -687,8 +708,12 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
.pcrel = false,
.length = 2,
.@"type" = switch (tag) {
.load_memory_got => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGEOFF12),
.load_memory_direct => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12),
.load_memory_got,
.load_memory_ptr_got,
=> @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGEOFF12),
.load_memory_direct,
.load_memory_ptr_direct,
=> @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12),
else => unreachable,
},
});

View File

@ -56,10 +56,22 @@ pub const Inst = struct {
dbg_line,
/// Bitwise Exclusive OR (shifted register)
eor_shifted_register,
/// Loads the contents into a register
///
/// Payload is `LoadMemoryPie`
load_memory_got,
/// Loads the contents into a register
///
/// Payload is `LoadMemoryPie`
load_memory_direct,
/// Loads the address into a register
///
/// Payload is `LoadMemoryPie`
load_memory_ptr_got,
/// Loads the address into a register
///
/// Payload is `LoadMemoryPie`
load_memory_ptr_direct,
/// Load Pair of Registers
ldp,
/// Pseudo-instruction: Load from stack

View File

@ -305,7 +305,6 @@ fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void {
}
test "alignment of function with c calling convention" {
if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
var runtime_nothing = &nothing;

View File

@ -48,7 +48,6 @@ const g1: i32 = 1233 + 1;
var g2: i32 = 0;
test "global variables" {
if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
try expect(g2 == 0);
g2 = g1;
try expect(g2 == 1234);
@ -604,7 +603,6 @@ test "comptime cast fn to ptr" {
}
test "equality compare fn ptrs" {
if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
var a = &emptyFn;
@ -612,7 +610,6 @@ test "equality compare fn ptrs" {
}
test "self reference through fn ptr field" {
if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;

View File

@ -6,7 +6,6 @@ const S = struct {
p: *S,
};
test "bug 2006" {
if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
var a: S = undefined;
a = S{ .p = undefined };

View File

@ -1013,7 +1013,6 @@ test "cast from array reference to fn: comptime fn ptr" {
try expect(@ptrToInt(f) == @ptrToInt(&global_array));
}
test "cast from array reference to fn: runtime fn ptr" {
if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) 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

View File

@ -81,7 +81,6 @@ fn assertLenIsZero(msg: []const u8) !void {
}
test "access len index of sentinel-terminated slice" {
if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
const S = struct {

View File

@ -66,7 +66,6 @@ const SmallStruct = struct {
};
test "lower unnamed constants" {
if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
var foo = SmallStruct{ .a = 1, .b = 255 };
try expect(foo.first() == 1);
try expect(foo.second() == 255);