@@ -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 ;
0 commit comments