authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-12 20:29:48+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-13 17:00:03+02:00
log91969ad908ebb0362eac994ba10cb23bce0a7a4c
tree6cc199fdc41afe00df6ce1eaeccf9ac1042a6b2c
parent4c5156544b1b96a4860f98ecac5c7abe47de5465
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: Fix tracking of function return values


1 files changed, 33 insertions(+), 2 deletions(-)

src/arch/arm/CodeGen.zig+33-2
......@@ -247,6 +247,31 @@ const BigTomb = struct {
247247 log.debug("%{d} => {}", .{ bt.inst, result });
248248 const branch = &bt.function.branch_stack.items[bt.function.branch_stack.items.len - 1];
249249 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 }
250275 }
251276 bt.function.finishAirBookkeeping();
252277 }
......@@ -3524,7 +3549,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
35243549 try self.register_manager.getReg(reg, null);
35253550 }
35263551
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: {
35283556 log.debug("airCall: return by reference", .{});
35293557 const ret_ty = fn_ty.fnReturnType();
35303558 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.
35403568 try self.genSetReg(ptr_ty, .r0, .{ .ptr_stack_offset = stack_offset });
35413569
35423570 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);
35443575
35453576 // Make space for the arguments passed via the stack
35463577 self.max_end_stack += info.stack_byte_count;