stage2 ARM: Fix tracking of function return values

This commit is contained in:
joachimschmidt557 2022-08-12 20:29:48 +02:00
parent 4c5156544b
commit 91969ad908
No known key found for this signature in database
GPG Key ID: E0B575BE2884ACC5

View File

@ -247,6 +247,31 @@ const BigTomb = struct {
log.debug("%{d} => {}", .{ bt.inst, result });
const branch = &bt.function.branch_stack.items[bt.function.branch_stack.items.len - 1];
branch.inst_table.putAssumeCapacityNoClobber(bt.inst, result);
switch (result) {
.register => |reg| {
// In some cases (such as bitcast), an operand
// may be the same MCValue as the result. If
// that operand died and was a register, it
// was freed by processDeath. We have to
// "re-allocate" the register.
if (bt.function.register_manager.isRegFree(reg)) {
bt.function.register_manager.getRegAssumeFree(reg, bt.inst);
}
},
.register_c_flag,
.register_v_flag,
=> |reg| {
if (bt.function.register_manager.isRegFree(reg)) {
bt.function.register_manager.getRegAssumeFree(reg, bt.inst);
}
bt.function.cpsr_flags_inst = bt.inst;
},
.cpsr_flags => {
bt.function.cpsr_flags_inst = bt.inst;
},
else => {},
}
}
bt.function.finishAirBookkeeping();
}
@ -3524,7 +3549,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
try self.register_manager.getReg(reg, null);
}
if (info.return_value == .stack_offset) {
// If returning by reference, r0 will contain the address of where
// to put the result into. In that case, make sure that r0 remains
// untouched by the parameter passing code
const r0_lock: ?RegisterLock = if (info.return_value == .stack_offset) blk: {
log.debug("airCall: return by reference", .{});
const ret_ty = fn_ty.fnReturnType();
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.
try self.genSetReg(ptr_ty, .r0, .{ .ptr_stack_offset = stack_offset });
info.return_value = .{ .stack_offset = stack_offset };
}
break :blk self.register_manager.lockRegAssumeUnused(.r0);
} else null;
defer if (r0_lock) |reg| self.register_manager.unlockReg(reg);
// Make space for the arguments passed via the stack
self.max_end_stack += info.stack_byte_count;