authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-23 19:29:47+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-23 19:29:47+01:00
log2f0299c3cf3ce52c973eec62c88e87596e2d5260
tree94451bc321d652e0308048ed018fb85b5ece8c24
parent2ca809c32a69c286568814043019e444c1c85ff2

x64: account for multiple returns from functions

This is necessary to correctly adjust for spilling of the %rdi register in the callee.

1 files changed, 8 insertions(+), 5 deletions(-)

src/arch/x86_64/CodeGen.zig+8-5
...@@ -49,7 +49,7 @@ arg_index: u32,...@@ -49,7 +49,7 @@ arg_index: u32,
49src_loc: Module.SrcLoc,49src_loc: Module.SrcLoc,
50stack_align: u32,50stack_align: u32,
5151
52ret_backpatch: ?Mir.Inst.Index = null,52ret_backpatches: std.ArrayListUnmanaged(Mir.Inst.Index) = .{},
53compare_flags_inst: ?Air.Inst.Index = null,53compare_flags_inst: ?Air.Inst.Index = null,
5454
55/// MIR Instructions55/// MIR Instructions
...@@ -310,6 +310,7 @@ pub fn generate(...@@ -310,6 +310,7 @@ pub fn generate(
310 std.AutoHashMap(Mir.Inst.Index, Air.Inst.Index).init(bin_file.allocator)310 std.AutoHashMap(Mir.Inst.Index, Air.Inst.Index).init(bin_file.allocator)
311 else {},311 else {},
312 };312 };
313 defer function.ret_backpatches.deinit(bin_file.allocator);
313 defer function.stack.deinit(bin_file.allocator);314 defer function.stack.deinit(bin_file.allocator);
314 defer function.blocks.deinit(bin_file.allocator);315 defer function.blocks.deinit(bin_file.allocator);
315 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);316 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
...@@ -473,8 +474,8 @@ fn gen(self: *Self) InnerError!void {...@@ -473,8 +474,8 @@ fn gen(self: *Self) InnerError!void {
473 };474 };
474 inline for (callee_preserved_regs) |reg, i| {475 inline for (callee_preserved_regs) |reg, i| {
475 if (self.register_manager.isRegAllocated(reg)) {476 if (self.register_manager.isRegAllocated(reg)) {
476 if (self.ret_backpatch) |inst| {477 if (reg.to64() == .rdi) {
477 if (reg.to64() == .rdi) {478 for (self.ret_backpatches.items) |inst| {
478 const ops = Mir.Ops.decode(self.mir_instructions.items(.ops)[inst]);479 const ops = Mir.Ops.decode(self.mir_instructions.items(.ops)[inst]);
479 self.mir_instructions.set(inst, Mir.Inst{480 self.mir_instructions.set(inst, Mir.Inst{
480 .tag = .mov,481 .tag = .mov,
...@@ -3312,7 +3313,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -3312,7 +3313,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
3312 self.register_manager.freezeRegs(&.{ .rax, .rcx, .rdi });3313 self.register_manager.freezeRegs(&.{ .rax, .rcx, .rdi });
3313 defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rdi });3314 defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rdi });
3314 const reg = try self.register_manager.allocReg(null);3315 const reg = try self.register_manager.allocReg(null);
3315 self.ret_backpatch = try self.addInst(.{3316 const backpatch = try self.addInst(.{
3316 .tag = .mov,3317 .tag = .mov,
3317 .ops = (Mir.Ops{3318 .ops = (Mir.Ops{
3318 .reg1 = reg,3319 .reg1 = reg,
...@@ -3320,6 +3321,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -3320,6 +3321,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
3320 }).encode(),3321 }).encode(),
3321 .data = undefined,3322 .data = undefined,
3322 });3323 });
3324 try self.ret_backpatches.append(self.gpa, backpatch);
3323 try self.genSetStack(ret_ty, 0, operand, .{3325 try self.genSetStack(ret_ty, 0, operand, .{
3324 .source_stack_base = .rbp,3326 .source_stack_base = .rbp,
3325 .dest_stack_base = reg,3327 .dest_stack_base = reg,
...@@ -3354,7 +3356,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -3354,7 +3356,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
3354 self.register_manager.freezeRegs(&.{ .rax, .rcx, .rdi });3356 self.register_manager.freezeRegs(&.{ .rax, .rcx, .rdi });
3355 defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rdi });3357 defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rdi });
3356 const reg = try self.register_manager.allocReg(null);3358 const reg = try self.register_manager.allocReg(null);
3357 self.ret_backpatch = try self.addInst(.{3359 const backpatch = try self.addInst(.{
3358 .tag = .mov,3360 .tag = .mov,
3359 .ops = (Mir.Ops{3361 .ops = (Mir.Ops{
3360 .reg1 = reg,3362 .reg1 = reg,
...@@ -3362,6 +3364,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -3362,6 +3364,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
3362 }).encode(),3364 }).encode(),
3363 .data = undefined,3365 .data = undefined,
3364 });3366 });
3367 try self.ret_backpatches.append(self.gpa, backpatch);
3365 try self.genInlineMemcpy(0, elem_ty, ptr, .{3368 try self.genInlineMemcpy(0, elem_ty, ptr, .{
3366 .source_stack_base = .rbp,3369 .source_stack_base = .rbp,
3367 .dest_stack_base = reg,3370 .dest_stack_base = reg,