Skip to content

Commit f46c80b

Browse files
stage2 AArch64: improve correctness of register aliases
Also implements ptr_elem_ptr
1 parent 508b90f commit f46c80b

File tree

1 file changed

+69
-14
lines changed

1 file changed

+69
-14
lines changed

src/arch/aarch64/CodeGen.zig

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,9 @@ fn binOpRegister(
13141314
const lhs_is_register = lhs == .register;
13151315
const rhs_is_register = rhs == .register;
13161316

1317+
if (lhs_is_register) assert(lhs.register == registerAlias(lhs.register, lhs_ty.abiSize(self.target.*)));
1318+
if (rhs_is_register) assert(rhs.register == registerAlias(rhs.register, rhs_ty.abiSize(self.target.*)));
1319+
13171320
const lhs_lock: ?RegisterLock = if (lhs_is_register)
13181321
self.register_manager.lockReg(lhs.register)
13191322
else
@@ -1343,13 +1346,22 @@ fn binOpRegister(
13431346
const new_lhs_lock = self.register_manager.lockReg(lhs_reg);
13441347
defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
13451348

1346-
const rhs_reg = if (rhs_is_register) rhs.register else blk: {
1349+
const rhs_reg = if (rhs_is_register)
1350+
// lhs is almost always equal to rhs, except in shifts. In
1351+
// order to guarantee that registers will have equal sizes, we
1352+
// use the register alias of rhs corresponding to the size of
1353+
// lhs.
1354+
registerAlias(rhs.register, lhs_ty.abiSize(self.target.*))
1355+
else blk: {
13471356
const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: {
13481357
break :inst Air.refToIndex(md.rhs).?;
13491358
} else null;
13501359

13511360
const raw_reg = try self.register_manager.allocReg(track_inst, gp);
1352-
const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));
1361+
1362+
// Here, we deliberately use lhs as lhs and rhs may differ in
1363+
// the case of shifts. See comment above.
1364+
const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
13531365

13541366
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
13551367

@@ -1458,6 +1470,8 @@ fn binOpImmediate(
14581470
) !MCValue {
14591471
const lhs_is_register = lhs == .register;
14601472

1473+
if (lhs_is_register) assert(lhs.register == registerAlias(lhs.register, lhs_ty.abiSize(self.target.*)));
1474+
14611475
const lhs_lock: ?RegisterLock = if (lhs_is_register)
14621476
self.register_manager.lockReg(lhs.register)
14631477
else
@@ -1698,21 +1712,52 @@ fn binOp(
16981712
null;
16991713
defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
17001714

1701-
const lhs_reg = if (lhs_is_register)
1702-
lhs.register
1715+
const rhs_lock: ?RegisterLock = if (rhs_is_register)
1716+
self.register_manager.lockReg(rhs.register)
17031717
else
1704-
try self.register_manager.allocReg(null, gp);
1718+
null;
1719+
defer if (rhs_lock) |reg| self.register_manager.unlockReg(reg);
1720+
1721+
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
1722+
1723+
const lhs_reg = if (lhs_is_register) lhs.register else blk: {
1724+
const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: {
1725+
break :inst Air.refToIndex(md.lhs).?;
1726+
} else null;
1727+
1728+
const raw_reg = try self.register_manager.allocReg(track_inst, gp);
1729+
const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
1730+
1731+
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
1732+
1733+
break :blk reg;
1734+
};
17051735
const new_lhs_lock = self.register_manager.lockReg(lhs_reg);
17061736
defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
17071737

1708-
const rhs_reg = if (rhs_is_register)
1709-
rhs.register
1710-
else
1711-
try self.register_manager.allocReg(null, gp);
1738+
const rhs_reg = if (rhs_is_register) rhs.register else blk: {
1739+
const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: {
1740+
break :inst Air.refToIndex(md.rhs).?;
1741+
} else null;
1742+
1743+
const raw_reg = try self.register_manager.allocReg(track_inst, gp);
1744+
const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));
1745+
1746+
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
1747+
1748+
break :blk reg;
1749+
};
17121750
const new_rhs_lock = self.register_manager.lockReg(rhs_reg);
17131751
defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);
17141752

1715-
const dest_regs = try self.register_manager.allocRegs(2, .{ null, null }, gp);
1753+
const dest_regs: [2]Register = blk: {
1754+
const raw_regs = try self.register_manager.allocRegs(2, .{ null, null }, gp);
1755+
const abi_size = lhs_ty.abiSize(self.target.*);
1756+
break :blk .{
1757+
registerAlias(raw_regs[0], abi_size),
1758+
registerAlias(raw_regs[1], abi_size),
1759+
};
1760+
};
17161761
const dest_regs_locks = self.register_manager.lockRegsAssumeUnused(2, dest_regs);
17171762
defer for (dest_regs_locks) |reg| {
17181763
self.register_manager.unlockReg(reg);
@@ -2037,7 +2082,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
20372082
try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
20382083

20392084
// cmp dest, truncated
2040-
_ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, Type.usize, Type.usize, null);
2085+
_ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, lhs_ty, lhs_ty, null);
20412086

20422087
try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
20432088
try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .condition_flags = .ne });
@@ -2753,7 +2798,15 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
27532798
fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
27542799
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
27552800
const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2756-
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_elem_ptr for {}", .{self.target.cpu.arch});
2801+
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2802+
const ptr_mcv = try self.resolveInst(extra.lhs);
2803+
const index_mcv = try self.resolveInst(extra.rhs);
2804+
2805+
const ptr_ty = self.air.typeOf(extra.lhs);
2806+
2807+
const addr = try self.binOp(.ptr_add, ptr_mcv, index_mcv, ptr_ty, Type.usize, null);
2808+
break :result addr;
2809+
};
27572810
return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
27582811
}
27592812

@@ -3219,6 +3272,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
32193272
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
32203273
const mcv = try self.resolveInst(operand);
32213274
const struct_ty = self.air.typeOf(operand);
3275+
const struct_field_ty = struct_ty.structFieldType(index);
32223276
const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
32233277

32243278
switch (mcv) {
@@ -3250,8 +3304,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
32503304
break :result field;
32513305
} else {
32523306
// Copy to new register
3253-
const dest_reg = try self.register_manager.allocReg(null, gp);
3254-
try self.genSetReg(struct_ty.structFieldType(index), dest_reg, field);
3307+
const raw_dest_reg = try self.register_manager.allocReg(null, gp);
3308+
const dest_reg = registerAlias(raw_dest_reg, struct_field_ty.abiSize(self.target.*));
3309+
try self.genSetReg(struct_field_ty, dest_reg, field);
32553310

32563311
break :result MCValue{ .register = dest_reg };
32573312
}

0 commit comments

Comments
 (0)