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
signature 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 {...@@ -130,6 +130,7 @@ pub fn main2() anyerror!void {
130 }130 }
131 if (builtin.zig_backend == .stage2_wasm or131 if (builtin.zig_backend == .stage2_wasm or
132 builtin.zig_backend == .stage2_x86_64 or132 builtin.zig_backend == .stage2_x86_64 or
133 builtin.zig_backend == .stage2_aarch64 or
133 builtin.zig_backend == .stage2_llvm or134 builtin.zig_backend == .stage2_llvm or
134 builtin.zig_backend == .stage2_c)135 builtin.zig_backend == .stage2_c)
135 {136 {
src/arch/aarch64/CodeGen.zig+45-7
...@@ -1016,8 +1016,27 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {...@@ -1016,8 +1016,27 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {
1016}1016}
10171017
1018fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {1018fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
1019 const stack_offset = try self.allocMemPtr(inst);1019 const result: MCValue = switch (self.ret_mcv) {
1020 return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none });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 });
1021}1040}
10221041
1023fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {1042fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
...@@ -3631,6 +3650,7 @@ fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type...@@ -3631,6 +3650,7 @@ fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type
3631}3650}
36323651
3633fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {3652fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {
3653 log.debug("store: storing {} to {}", .{ value, ptr });
3634 const abi_size = value_ty.abiSize(self.target.*);3654 const abi_size = value_ty.abiSize(self.target.*);
36353655
3636 switch (ptr) {3656 switch (ptr) {
...@@ -3655,6 +3675,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3655,6 +3675,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3655 .dead => unreachable,3675 .dead => unreachable,
3656 .undef => unreachable,3676 .undef => unreachable,
3657 .register => |value_reg| {3677 .register => |value_reg| {
3678 log.debug("store: register {} to {}", .{ value_reg, addr_reg });
3658 try self.genStrRegister(value_reg, addr_reg, value_ty);3679 try self.genStrRegister(value_reg, addr_reg, value_ty);
3659 },3680 },
3660 else => {3681 else => {
...@@ -3673,8 +3694,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3673,8 +3694,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3673 self.register_manager.unlockReg(reg);3694 self.register_manager.unlockReg(reg);
3674 };3695 };
36753696
3676 const src_reg = addr_reg;3697 const src_reg = regs[0];
3677 const dst_reg = regs[0];3698 const dst_reg = addr_reg;
3678 const len_reg = regs[1];3699 const len_reg = regs[1];
3679 const count_reg = regs[2];3700 const count_reg = regs[2];
3680 const tmp_reg = regs[3];3701 const tmp_reg = regs[3];
...@@ -3684,7 +3705,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3684,7 +3705,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3684 // sub src_reg, fp, #off3705 // sub src_reg, fp, #off
3685 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });3706 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });
3686 },3707 },
3687 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }),
3688 .stack_argument_offset => |off| {3708 .stack_argument_offset => |off| {
3689 _ = try self.addInst(.{3709 _ = try self.addInst(.{
3690 .tag = .ldr_ptr_stack_argument,3710 .tag = .ldr_ptr_stack_argument,
...@@ -3694,6 +3714,24 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -3694,6 +3714,24 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3694 } },3714 } },
3695 });3715 });
3696 },3716 },
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 },
3697 else => return self.fail("TODO store {} to register", .{value}),3735 else => return self.fail("TODO store {} to register", .{value}),
3698 }3736 }
36993737
...@@ -4428,7 +4466,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4428,7 +4466,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4428 if (else_value == .dead)4466 if (else_value == .dead)
4429 continue;4467 continue;
4430 // The instruction is only overridden in the else branch.4468 // 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;
4432 while (true) {4470 while (true) {
4433 i -= 1; // If this overflows, the question is: why wasn't the instruction marked dead?4471 i -= 1; // If this overflows, the question is: why wasn't the instruction marked dead?
4434 if (self.branch_stack.items[i].inst_table.get(else_key)) |mcv| {4472 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 {...@@ -4455,7 +4493,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4455 if (then_value == .dead)4493 if (then_value == .dead)
4456 continue;4494 continue;
4457 const parent_mcv = blk: {4495 const parent_mcv = blk: {
4458 var i: usize = self.branch_stack.items.len - 2;4496 var i: usize = self.branch_stack.items.len - 1;
4459 while (true) {4497 while (true) {
4460 i -= 1;4498 i -= 1;
4461 if (self.branch_stack.items[i].inst_table.get(then_key)) |mcv| {4499 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 {...@@ -1191,42 +1191,50 @@ fn mirNop(emit: *Emit) !void {
1191 try emit.writeInstruction(Instruction.nop());1191 try emit.writeInstruction(Instruction.nop());
1192}1192}
11931193
1194fn regListIsSet(reg_list: u32, reg: Register) bool {
1195 return reg_list & @as(u32, 1) << @intCast(u5, reg.id()) != 0;
1196}
1197
1194fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void {1198fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void {
1195 const tag = emit.mir.instructions.items(.tag)[inst];1199 const tag = emit.mir.instructions.items(.tag)[inst];
1196 const reg_list = emit.mir.instructions.items(.data)[inst].reg_list;1200 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
1200 // sp must be aligned at all times, so we only use stp and ldp1204 // sp must be aligned at all times, so we only use stp and ldp
1201 // instructions for minimal instruction count. However, if we do1205 // instructions for minimal instruction count.
1202 // not have an even number of registers, we use str and ldr1206 //
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.
1203 const number_of_regs = @popCount(reg_list);1211 const number_of_regs = @popCount(reg_list);
1212 const odd_number_of_regs = number_of_regs % 2 != 0;
12041213
1205 switch (tag) {1214 switch (tag) {
1206 .pop_regs => {1215 .pop_regs => {
1207 var i: u6 = 32;1216 var i: u6 = 32;
1208 var count: u6 = 0;1217 var count: u6 = 0;
1209 var other_reg: Register = undefined;1218 var other_reg: ?Register = null;
1210 while (i > 0) : (i -= 1) {1219 while (i > 0) : (i -= 1) {
1211 const reg = @intToEnum(Register, i - 1);1220 const reg = @intToEnum(Register, i - 1);
1212 if (reg_list & @as(u32, 1) << @intCast(u5, reg.id()) != 0) {1221 if (regListIsSet(reg_list, reg)) {
1213 if (count % 2 == 0) {1222 if (count == 0 and odd_number_of_regs) {
1214 if (count == number_of_regs - 1) {1223 try emit.writeInstruction(Instruction.ldr(
1215 try emit.writeInstruction(Instruction.ldr(1224 reg,
1216 reg,1225 .sp,
1217 .sp,1226 Instruction.LoadStoreOffset.imm_post_index(16),
1218 Instruction.LoadStoreOffset.imm_post_index(16),1227 ));
1219 ));1228 } else if (other_reg) |r| {
1220 } else {
1221 other_reg = reg;
1222 }
1223 } else {
1224 try emit.writeInstruction(Instruction.ldp(1229 try emit.writeInstruction(Instruction.ldp(
1225 reg,1230 reg,
1226 other_reg,1231 r,
1227 .sp,1232 .sp,
1228 Instruction.LoadStorePairOffset.post_index(16),1233 Instruction.LoadStorePairOffset.post_index(16),
1229 ));1234 ));
1235 other_reg = null;
1236 } else {
1237 other_reg = reg;
1230 }1238 }
1231 count += 1;1239 count += 1;
1232 }1240 }
...@@ -1236,27 +1244,26 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -1236,27 +1244,26 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void {
1236 .push_regs => {1244 .push_regs => {
1237 var i: u6 = 0;1245 var i: u6 = 0;
1238 var count: u6 = 0;1246 var count: u6 = 0;
1239 var other_reg: Register = undefined;1247 var other_reg: ?Register = null;
1240 while (i < 32) : (i += 1) {1248 while (i < 32) : (i += 1) {
1241 const reg = @intToEnum(Register, i);1249 const reg = @intToEnum(Register, i);
1242 if (reg_list & @as(u32, 1) << @intCast(u5, reg.id()) != 0) {1250 if (regListIsSet(reg_list, reg)) {
1243 if (count % 2 == 0) {1251 if (count == number_of_regs - 1 and odd_number_of_regs) {
1244 if (count == number_of_regs - 1) {1252 try emit.writeInstruction(Instruction.str(
1245 try emit.writeInstruction(Instruction.str(1253 reg,
1246 reg,1254 .sp,
1247 .sp,1255 Instruction.LoadStoreOffset.imm_pre_index(-16),
1248 Instruction.LoadStoreOffset.imm_pre_index(-16),1256 ));
1249 ));1257 } else if (other_reg) |r| {
1250 } else {
1251 other_reg = reg;
1252 }
1253 } else {
1254 try emit.writeInstruction(Instruction.stp(1258 try emit.writeInstruction(Instruction.stp(
1255 other_reg,1259 r,
1256 reg,1260 reg,
1257 .sp,1261 .sp,
1258 Instruction.LoadStorePairOffset.pre_index(-16),1262 Instruction.LoadStorePairOffset.pre_index(-16),
1259 ));1263 ));
1264 other_reg = null;
1265 } else {
1266 other_reg = reg;
1260 }1267 }
1261 count += 1;1268 count += 1;
1262 }1269 }