| ... | @@ -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 |
| 898 | fn spillCompareFlagsIfOccupied(self: *Self) !void { | 898 | fn 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 flags | 908 | else => unreachable, // mcv doesn't occupy the compare flags |
| 908 | } | 909 | }; |
| 909 | | 910 | |
| 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 }); |
| 913 | | 913 | |
| ... | @@ -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); |
| 916 | | 916 | |
| 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 | } |
| 920 | | 929 | |
| ... | @@ -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); |
| 1977 | | 1986 | |
| 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; |
| 3678 | | 3687 | |
| 3679 | try self.branch_stack.append(.{}); | 3688 | try self.branch_stack.append(.{}); |
| | 3689 | errdefer { |
| | 3690 | _ = self.branch_stack.pop(); |
| | 3691 | } |
| 3680 | | 3692 | |
| 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, |