authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-07 22:35:36+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-07 22:35:41+02:00
log756ddf092562acb8b552c31ad458b9ae1754e77c
treee154677c7aa597abef899f4b3c92130912e09eed
parentf57b059e58253af3718c5b17fefc40c47b33e63c

arm: fix CF flags spilling and implement genSetStack for reg with overflow flags


1 files changed, 48 insertions(+), 8 deletions(-)

src/arch/arm/CodeGen.zig+48-8
...@@ -898,16 +898,16 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void...@@ -898,16 +898,16 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
898fn spillCompareFlagsIfOccupied(self: *Self) !void {898fn spillCompareFlagsIfOccupied(self: *Self) !void {
899 if (self.compare_flags_inst) |inst_to_save| {899 if (self.compare_flags_inst) |inst_to_save| {
900 const mcv = self.getResolvedInstValue(inst_to_save);900 const mcv = self.getResolvedInstValue(inst_to_save);
901 switch (mcv) {901 const new_mcv = switch (mcv) {
902 .compare_flags_signed,902 .compare_flags_signed,
903 .compare_flags_unsigned,903 .compare_flags_unsigned,
904 => try self.allocRegOrMem(inst_to_save, true),
904 .register_c_flag,905 .register_c_flag,
905 .register_v_flag,906 .register_v_flag,
906 => {},907 => try self.allocRegOrMem(inst_to_save, false),
907 else => unreachable, // mcv doesn't occupy the compare flags908 else => unreachable, // mcv doesn't occupy the compare flags
908 }909 };
909910
910 const new_mcv = try self.allocRegOrMem(inst_to_save, true);
911 try self.setRegOrMem(self.air.typeOfIndex(inst_to_save), new_mcv, mcv);911 try self.setRegOrMem(self.air.typeOfIndex(inst_to_save), new_mcv, mcv);
912 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });912 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });
913913
...@@ -915,6 +915,15 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {...@@ -915,6 +915,15 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
915 try branch.inst_table.put(self.gpa, inst_to_save, new_mcv);915 try branch.inst_table.put(self.gpa, inst_to_save, new_mcv);
916916
917 self.compare_flags_inst = null;917 self.compare_flags_inst = null;
918
919 // TODO consolidate with register manager and spillInstruction
920 // this call should really belong in the register manager!
921 switch (mcv) {
922 .register_c_flag,
923 .register_v_flag,
924 => |reg| self.register_manager.freeReg(reg),
925 else => {},
926 }
918 }927 }
919}928}
920929
...@@ -1972,8 +1981,8 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1972,8 +1981,8 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1972 .register => |reg| reg,1981 .register => |reg| reg,
1973 else => try self.copyToTmpRegister(Type.usize, index_mcv),1982 else => try self.copyToTmpRegister(Type.usize, index_mcv),
1974 };1983 };
1975 const index_reg_lock = self.register_manager.lockRegAssumeUnused(index_reg);1984 const index_reg_lock = self.register_manager.lockReg(index_reg);
1976 defer self.register_manager.unlockReg(index_reg_lock);1985 defer if (index_reg_lock) |lock| self.register_manager.unlockReg(lock);
19771986
1978 const tag: Mir.Inst.Tag = switch (elem_size) {1987 const tag: Mir.Inst.Tag = switch (elem_size) {
1979 1 => .ldrb,1988 1 => .ldrb,
...@@ -3677,6 +3686,9 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3677,6 +3686,9 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
3677 const parent_compare_flags_inst = self.compare_flags_inst;3686 const parent_compare_flags_inst = self.compare_flags_inst;
36783687
3679 try self.branch_stack.append(.{});3688 try self.branch_stack.append(.{});
3689 errdefer {
3690 _ = self.branch_stack.pop();
3691 }
36803692
3681 try self.ensureProcessDeathCapacity(liveness_condbr.then_deaths.len);3693 try self.ensureProcessDeathCapacity(liveness_condbr.then_deaths.len);
3682 for (liveness_condbr.then_deaths) |operand| {3694 for (liveness_condbr.then_deaths) |operand| {
...@@ -4285,8 +4297,36 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4285,8 +4297,36 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4285 },4297 },
4286 .register_c_flag,4298 .register_c_flag,
4287 .register_v_flag,4299 .register_v_flag,
4288 => {4300 => |reg| {
4289 return self.fail("TODO implement genSetStack {}", .{mcv});4301 const reg_lock = self.register_manager.lockReg(reg);
4302 defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);
4303
4304 const wrapped_ty = ty.structFieldType(0);
4305 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg });
4306
4307 const overflow_bit_ty = ty.structFieldType(1);
4308 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));
4309 const cond_reg = try self.register_manager.allocReg(null);
4310
4311 // C flag: movcs reg, #1
4312 // V flag: movvs reg, #1
4313 _ = try self.addInst(.{
4314 .tag = .mov,
4315 .cond = switch (mcv) {
4316 .register_c_flag => .cs,
4317 .register_v_flag => .vs,
4318 else => unreachable,
4319 },
4320 .data = .{ .rr_op = .{
4321 .rd = cond_reg,
4322 .rn = .r0,
4323 .op = Instruction.Operand.fromU32(1).?,
4324 } },
4325 });
4326
4327 try self.genSetStack(overflow_bit_ty, stack_offset - overflow_bit_offset, .{
4328 .register = cond_reg,
4329 });
4290 },4330 },
4291 .memory,4331 .memory,
4292 .stack_argument_offset,4332 .stack_argument_offset,