| ... | ... | @@ -247,6 +247,31 @@ const BigTomb = struct { |
| 247 | 247 | log.debug("%{d} => {}", .{ bt.inst, result }); |
| 248 | 248 | const branch = &bt.function.branch_stack.items[bt.function.branch_stack.items.len - 1]; |
| 249 | 249 | branch.inst_table.putAssumeCapacityNoClobber(bt.inst, result); |
| 250 | |
| 251 | switch (result) { |
| 252 | .register => |reg| { |
| 253 | // In some cases (such as bitcast), an operand |
| 254 | // may be the same MCValue as the result. If |
| 255 | // that operand died and was a register, it |
| 256 | // was freed by processDeath. We have to |
| 257 | // "re-allocate" the register. |
| 258 | if (bt.function.register_manager.isRegFree(reg)) { |
| 259 | bt.function.register_manager.getRegAssumeFree(reg, bt.inst); |
| 260 | } |
| 261 | }, |
| 262 | .register_c_flag, |
| 263 | .register_v_flag, |
| 264 | => |reg| { |
| 265 | if (bt.function.register_manager.isRegFree(reg)) { |
| 266 | bt.function.register_manager.getRegAssumeFree(reg, bt.inst); |
| 267 | } |
| 268 | bt.function.cpsr_flags_inst = bt.inst; |
| 269 | }, |
| 270 | .cpsr_flags => { |
| 271 | bt.function.cpsr_flags_inst = bt.inst; |
| 272 | }, |
| 273 | else => {}, |
| 274 | } |
| 250 | 275 | } |
| 251 | 276 | bt.function.finishAirBookkeeping(); |
| 252 | 277 | } |
| ... | ... | @@ -3524,7 +3549,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3524 | 3549 | try self.register_manager.getReg(reg, null); |
| 3525 | 3550 | } |
| 3526 | 3551 | |
| 3527 | | if (info.return_value == .stack_offset) { |
| 3552 | // If returning by reference, r0 will contain the address of where |
| 3553 | // to put the result into. In that case, make sure that r0 remains |
| 3554 | // untouched by the parameter passing code |
| 3555 | const r0_lock: ?RegisterLock = if (info.return_value == .stack_offset) blk: { |
| 3528 | 3556 | log.debug("airCall: return by reference", .{}); |
| 3529 | 3557 | const ret_ty = fn_ty.fnReturnType(); |
| 3530 | 3558 | const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); |
| ... | ... | @@ -3540,7 +3568,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3540 | 3568 | try self.genSetReg(ptr_ty, .r0, .{ .ptr_stack_offset = stack_offset }); |
| 3541 | 3569 | |
| 3542 | 3570 | info.return_value = .{ .stack_offset = stack_offset }; |
| 3543 | | } |
| 3571 | |
| 3572 | break :blk self.register_manager.lockRegAssumeUnused(.r0); |
| 3573 | } else null; |
| 3574 | defer if (r0_lock) |reg| self.register_manager.unlockReg(reg); |
| 3544 | 3575 | |
| 3545 | 3576 | // Make space for the arguments passed via the stack |
| 3546 | 3577 | self.max_end_stack += info.stack_byte_count; |