Skip to content

Commit 91969ad

Browse files
stage2 ARM: Fix tracking of function return values
1 parent 4c51565 commit 91969ad

File tree

1 file changed

+33
-2
lines changed

1 file changed

+33
-2
lines changed

src/arch/arm/CodeGen.zig

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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;

0 commit comments

Comments
 (0)