authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-10-31 19:50:02+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-11-01 20:44:18+01:00
log3051fab97cbe89f3be8ec2aab36ca0e60fd953f9
treed8599199275f0e61944c94d9f55d37c3f183857d
parent4e0779813b5a25755f6a5f12e8ec05304abb2337
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: misc fixes, enable printing in test runner

- Fixed missing airRetPtr implementation - Fixed wrong pop_regs order - Fixed wrong source and destination register in store

3 files changed, 84 insertions(+), 38 deletions(-)

lib/test_runner.zig+1
......@@ -130,6 +130,7 @@ pub fn main2() anyerror!void {
130130 }
131131 if (builtin.zig_backend == .stage2_wasm or
132132 builtin.zig_backend == .stage2_x86_64 or
133 builtin.zig_backend == .stage2_aarch64 or
133134 builtin.zig_backend == .stage2_llvm or
134135 builtin.zig_backend == .stage2_c)
135136 {
src/arch/aarch64/CodeGen.zig+45-7
......@@ -1016,8 +1016,27 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {
10161016}
10171017
10181018fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
1019 const stack_offset = try self.allocMemPtr(inst);
1020 return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none });
1019 const result: MCValue = switch (self.ret_mcv) {
1020 .none, .register => .{ .ptr_stack_offset = try self.allocMemPtr(inst) },
1021 .stack_offset => blk: {
1022 // self.ret_mcv is an address to where this function
1023 // should store its result into
1024 const ret_ty = self.fn_type.fnReturnType();
1025 var ptr_ty_payload: Type.Payload.ElemType = .{
1026 .base = .{ .tag = .single_mut_pointer },
1027 .data = ret_ty,
1028 };
1029 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
1030
1031 // addr_reg will contain the address of where to store the
1032 // result into
1033 const addr_reg = try self.copyToTmpRegister(ptr_ty, self.ret_mcv);
1034 break :blk .{ .register = addr_reg };
1035 },
1036 else => unreachable, // invalid return result
1037 };
1038
1039 return self.finishAir(inst, result, .{ .none, .none, .none });
10211040}
10221041
10231042fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
......@@ -3631,6 +3650,7 @@ fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type
36313650}
36323651
36333652fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {
3653 log.debug("store: storing {} to {}", .{ value, ptr });
36343654 const abi_size = value_ty.abiSize(self.target.*);
36353655
36363656 switch (ptr) {
......@@ -3655,6 +3675,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
36553675 .dead => unreachable,
36563676 .undef => unreachable,
36573677 .register => |value_reg| {
3678 log.debug("store: register {} to {}", .{ value_reg, addr_reg });
36583679 try self.genStrRegister(value_reg, addr_reg, value_ty);
36593680 },
36603681 else => {
......@@ -3673,8 +3694,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
36733694 self.register_manager.unlockReg(reg);
36743695 };
36753696
3676 const src_reg = addr_reg;
3677 const dst_reg = regs[0];
3697 const src_reg = regs[0];
3698 const dst_reg = addr_reg;
36783699 const len_reg = regs[1];
36793700 const count_reg = regs[2];
36803701 const tmp_reg = regs[3];
......@@ -3684,7 +3705,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
36843705 // sub src_reg, fp, #off
36853706 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });
36863707 },
3687 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }),
36883708 .stack_argument_offset => |off| {
36893709 _ = try self.addInst(.{
36903710 .tag = .ldr_ptr_stack_argument,
......@@ -3694,6 +3714,24 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
36943714 } },
36953715 });
36963716 },
3717 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }),
3718 .linker_load => |load_struct| {
3719 const tag: Mir.Inst.Tag = switch (load_struct.@"type") {
3720 .got => .load_memory_ptr_got,
3721 .direct => .load_memory_ptr_direct,
3722 };
3723 const mod = self.bin_file.options.module.?;
3724 _ = try self.addInst(.{
3725 .tag = tag,
3726 .data = .{
3727 .payload = try self.addExtra(Mir.LoadMemoryPie{
3728 .register = @enumToInt(src_reg),
3729 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index,
3730 .sym_index = load_struct.sym_index,
3731 }),
3732 },
3733 });
3734 },
36973735 else => return self.fail("TODO store {} to register", .{value}),
36983736 }
36993737
......@@ -4428,7 +4466,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
44284466 if (else_value == .dead)
44294467 continue;
44304468 // The instruction is only overridden in the else branch.
4431 var i: usize = self.branch_stack.items.len - 2;
4469 var i: usize = self.branch_stack.items.len - 1;
44324470 while (true) {
44334471 i -= 1; // If this overflows, the question is: why wasn't the instruction marked dead?
44344472 if (self.branch_stack.items[i].inst_table.get(else_key)) |mcv| {
......@@ -4455,7 +4493,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
44554493 if (then_value == .dead)
44564494 continue;
44574495 const parent_mcv = blk: {
4458 var i: usize = self.branch_stack.items.len - 2;
4496 var i: usize = self.branch_stack.items.len - 1;
44594497 while (true) {
44604498 i -= 1;
44614499 if (self.branch_stack.items[i].inst_table.get(then_key)) |mcv| {
src/arch/aarch64/Emit.zig+38-31
......@@ -1191,42 +1191,50 @@ fn mirNop(emit: *Emit) !void {
11911191 try emit.writeInstruction(Instruction.nop());
11921192}
11931193
1194fn regListIsSet(reg_list: u32, reg: Register) bool {
1195 return reg_list & @as(u32, 1) << @intCast(u5, reg.id()) != 0;
1196}
1197
11941198fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void {
11951199 const tag = emit.mir.instructions.items(.tag)[inst];
11961200 const reg_list = emit.mir.instructions.items(.data)[inst].reg_list;
11971201
1198 if (reg_list & @as(u32, 1) << 31 != 0) return emit.fail("xzr is not a valid register for {}", .{tag});
1202 if (regListIsSet(reg_list, .xzr)) return emit.fail("xzr is not a valid register for {}", .{tag});
11991203
12001204 // sp must be aligned at all times, so we only use stp and ldp
1201 // instructions for minimal instruction count. However, if we do
1202 // not have an even number of registers, we use str and ldr
1205 // instructions for minimal instruction count.
1206 //
1207 // However, if we have an odd number of registers, for pop_regs we
1208 // use one ldr instruction followed by zero or more ldp
1209 // instructions; for push_regs we use zero or more stp
1210 // instructions followed by one str instruction.
12031211 const number_of_regs = @popCount(reg_list);
1212 const odd_number_of_regs = number_of_regs % 2 != 0;
12041213
12051214 switch (tag) {
12061215 .pop_regs => {
12071216 var i: u6 = 32;
12081217 var count: u6 = 0;
1209 var other_reg: Register = undefined;
1218 var other_reg: ?Register = null;
12101219 while (i > 0) : (i -= 1) {
12111220 const reg = @intToEnum(Register, i - 1);
1212 if (reg_list & @as(u32, 1) << @intCast(u5, reg.id()) != 0) {
1213 if (count % 2 == 0) {
1214 if (count == number_of_regs - 1) {
1215 try emit.writeInstruction(Instruction.ldr(
1216 reg,
1217 .sp,
1218 Instruction.LoadStoreOffset.imm_post_index(16),
1219 ));
1220 } else {
1221 other_reg = reg;
1222 }
1223 } else {
1221 if (regListIsSet(reg_list, reg)) {
1222 if (count == 0 and odd_number_of_regs) {
1223 try emit.writeInstruction(Instruction.ldr(
1224 reg,
1225 .sp,
1226 Instruction.LoadStoreOffset.imm_post_index(16),
1227 ));
1228 } else if (other_reg) |r| {
12241229 try emit.writeInstruction(Instruction.ldp(
12251230 reg,
1226 other_reg,
1231 r,
12271232 .sp,
12281233 Instruction.LoadStorePairOffset.post_index(16),
12291234 ));
1235 other_reg = null;
1236 } else {
1237 other_reg = reg;
12301238 }
12311239 count += 1;
12321240 }
......@@ -1236,27 +1244,26 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void {
12361244 .push_regs => {
12371245 var i: u6 = 0;
12381246 var count: u6 = 0;
1239 var other_reg: Register = undefined;
1247 var other_reg: ?Register = null;
12401248 while (i < 32) : (i += 1) {
12411249 const reg = @intToEnum(Register, i);
1242 if (reg_list & @as(u32, 1) << @intCast(u5, reg.id()) != 0) {
1243 if (count % 2 == 0) {
1244 if (count == number_of_regs - 1) {
1245 try emit.writeInstruction(Instruction.str(
1246 reg,
1247 .sp,
1248 Instruction.LoadStoreOffset.imm_pre_index(-16),
1249 ));
1250 } else {
1251 other_reg = reg;
1252 }
1253 } else {
1250 if (regListIsSet(reg_list, reg)) {
1251 if (count == number_of_regs - 1 and odd_number_of_regs) {
1252 try emit.writeInstruction(Instruction.str(
1253 reg,
1254 .sp,
1255 Instruction.LoadStoreOffset.imm_pre_index(-16),
1256 ));
1257 } else if (other_reg) |r| {
12541258 try emit.writeInstruction(Instruction.stp(
1255 other_reg,
1259 r,
12561260 reg,
12571261 .sp,
12581262 Instruction.LoadStorePairOffset.pre_index(-16),
12591263 ));
1264 other_reg = null;
1265 } else {
1266 other_reg = reg;
12601267 }
12611268 count += 1;
12621269 }