mirror of
https://github.com/ziglang/zig.git
synced 2025-12-12 17:23:09 +00:00
arm: fix CF flags spilling and implement genSetStack for reg with overflow flags
This commit is contained in:
parent
f57b059e58
commit
756ddf0925
@ -898,16 +898,16 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
|
||||
fn spillCompareFlagsIfOccupied(self: *Self) !void {
|
||||
if (self.compare_flags_inst) |inst_to_save| {
|
||||
const mcv = self.getResolvedInstValue(inst_to_save);
|
||||
switch (mcv) {
|
||||
const new_mcv = switch (mcv) {
|
||||
.compare_flags_signed,
|
||||
.compare_flags_unsigned,
|
||||
=> try self.allocRegOrMem(inst_to_save, true),
|
||||
.register_c_flag,
|
||||
.register_v_flag,
|
||||
=> {},
|
||||
=> try self.allocRegOrMem(inst_to_save, false),
|
||||
else => unreachable, // mcv doesn't occupy the compare flags
|
||||
}
|
||||
};
|
||||
|
||||
const new_mcv = try self.allocRegOrMem(inst_to_save, true);
|
||||
try self.setRegOrMem(self.air.typeOfIndex(inst_to_save), new_mcv, mcv);
|
||||
log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });
|
||||
|
||||
@ -915,6 +915,15 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
|
||||
try branch.inst_table.put(self.gpa, inst_to_save, new_mcv);
|
||||
|
||||
self.compare_flags_inst = null;
|
||||
|
||||
// TODO consolidate with register manager and spillInstruction
|
||||
// this call should really belong in the register manager!
|
||||
switch (mcv) {
|
||||
.register_c_flag,
|
||||
.register_v_flag,
|
||||
=> |reg| self.register_manager.freeReg(reg),
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1972,8 +1981,8 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
|
||||
.register => |reg| reg,
|
||||
else => try self.copyToTmpRegister(Type.usize, index_mcv),
|
||||
};
|
||||
const index_reg_lock = self.register_manager.lockRegAssumeUnused(index_reg);
|
||||
defer self.register_manager.unlockReg(index_reg_lock);
|
||||
const index_reg_lock = self.register_manager.lockReg(index_reg);
|
||||
defer if (index_reg_lock) |lock| self.register_manager.unlockReg(lock);
|
||||
|
||||
const tag: Mir.Inst.Tag = switch (elem_size) {
|
||||
1 => .ldrb,
|
||||
@ -3677,6 +3686,9 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const parent_compare_flags_inst = self.compare_flags_inst;
|
||||
|
||||
try self.branch_stack.append(.{});
|
||||
errdefer {
|
||||
_ = self.branch_stack.pop();
|
||||
}
|
||||
|
||||
try self.ensureProcessDeathCapacity(liveness_condbr.then_deaths.len);
|
||||
for (liveness_condbr.then_deaths) |operand| {
|
||||
@ -4285,8 +4297,36 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
|
||||
},
|
||||
.register_c_flag,
|
||||
.register_v_flag,
|
||||
=> {
|
||||
return self.fail("TODO implement genSetStack {}", .{mcv});
|
||||
=> |reg| {
|
||||
const reg_lock = self.register_manager.lockReg(reg);
|
||||
defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);
|
||||
|
||||
const wrapped_ty = ty.structFieldType(0);
|
||||
try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg });
|
||||
|
||||
const overflow_bit_ty = ty.structFieldType(1);
|
||||
const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));
|
||||
const cond_reg = try self.register_manager.allocReg(null);
|
||||
|
||||
// C flag: movcs reg, #1
|
||||
// V flag: movvs reg, #1
|
||||
_ = try self.addInst(.{
|
||||
.tag = .mov,
|
||||
.cond = switch (mcv) {
|
||||
.register_c_flag => .cs,
|
||||
.register_v_flag => .vs,
|
||||
else => unreachable,
|
||||
},
|
||||
.data = .{ .rr_op = .{
|
||||
.rd = cond_reg,
|
||||
.rn = .r0,
|
||||
.op = Instruction.Operand.fromU32(1).?,
|
||||
} },
|
||||
});
|
||||
|
||||
try self.genSetStack(overflow_bit_ty, stack_offset - overflow_bit_offset, .{
|
||||
.register = cond_reg,
|
||||
});
|
||||
},
|
||||
.memory,
|
||||
.stack_argument_offset,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user