authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-16 20:35:03+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-16 20:35:03+01:00
log09d468b237e58dd70cfa0a4311efab5ddabc9f95
tree47d75db266872db5e4c4cad0c95ee1a2ba51febe
parentd3edf298d18ff89bb0e0a3bfcee84a9fb63b1c6b

x64: overhaul stack handling mechanics

Now, the abstracted stack offsets grow in the same direction as the real stack values in hardware, and allocating stack memory is done by the taking the last stack offset, adding required abi size and aligning to the required abi align. Stack handling is now more natural as it aligns itself with how it works in hardware; hence stepping through the debugger and printing out different stack values is intuitive. Finally, the stack pointers are now correctly aligned to the required (and not necessarily natural) alignment.

3 files changed, 64 insertions(+), 81 deletions(-)

src/arch/x86_64/CodeGen.zig+59-76
......@@ -810,8 +810,8 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u
810810 if (abi_align > self.stack_align)
811811 self.stack_align = abi_align;
812812 // TODO find a free slot instead of always appending
813 const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align);
814 self.next_stack_offset = offset + abi_size;
813 const offset = mem.alignForwardGeneric(u32, self.next_stack_offset + abi_size, abi_align);
814 self.next_stack_offset = offset;
815815 if (self.next_stack_offset > self.max_end_stack)
816816 self.max_end_stack = self.next_stack_offset;
817817 try self.stack.putNoClobber(self.gpa, offset, .{
......@@ -823,7 +823,8 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u
823823
824824/// Use a pointer instruction as the basis for allocating stack memory.
825825fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
826 const elem_ty = self.air.typeOfIndex(inst).elemType();
826 const ptr_ty = self.air.typeOfIndex(inst);
827 const elem_ty = ptr_ty.elemType();
827828
828829 if (!elem_ty.hasRuntimeBits()) {
829830 return self.allocMem(inst, 8, 8);
......@@ -833,7 +834,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
833834 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty});
834835 };
835836 // TODO swap this for inst.ty.ptrAlign
836 const abi_align = elem_ty.abiAlignment(self.target.*);
837 const abi_align = ptr_ty.ptrAlignment(self.target.*);
837838 return self.allocMem(inst, abi_size, abi_align);
838839}
839840
......@@ -1148,8 +1149,8 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
11481149 const len_ty = self.air.typeOf(bin_op.rhs);
11491150
11501151 const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16));
1151 try self.genSetStack(ptr_ty, stack_offset + 8, ptr);
1152 try self.genSetStack(len_ty, stack_offset, len);
1152 try self.genSetStack(ptr_ty, stack_offset, ptr);
1153 try self.genSetStack(len_ty, stack_offset - 8, len);
11531154 const result = MCValue{ .stack_offset = stack_offset };
11541155
11551156 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
......@@ -1455,7 +1456,7 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
14551456 const dst_mcv: MCValue = blk: {
14561457 switch (operand) {
14571458 .stack_offset => |off| {
1458 break :blk MCValue{ .stack_offset = off + 8 };
1459 break :blk MCValue{ .stack_offset = off };
14591460 },
14601461 else => return self.fail("TODO implement slice_ptr for {}", .{operand}),
14611462 }
......@@ -1472,7 +1473,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
14721473 const dst_mcv: MCValue = blk: {
14731474 switch (operand) {
14741475 .stack_offset => |off| {
1475 break :blk MCValue{ .stack_offset = off };
1476 break :blk MCValue{ .stack_offset = off - 8 };
14761477 },
14771478 else => return self.fail("TODO implement slice_len for {}", .{operand}),
14781479 }
......@@ -1540,7 +1541,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
15401541 .reg2 = .rbp,
15411542 .flags = 0b01,
15421543 }).encode(),
1543 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + 16)) },
1544 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off)) },
15441545 });
15451546 },
15461547 else => return self.fail("TODO implement slice_elem_val when slice is {}", .{slice_mcv}),
......@@ -1571,7 +1572,6 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
15711572 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
15721573 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
15731574 const array_ty = self.air.typeOf(bin_op.lhs);
1574 const array_abi_size = array_ty.abiSize(self.target.*);
15751575 const array = try self.resolveInst(bin_op.lhs);
15761576 array.freezeIfRegister(&self.register_manager);
15771577 defer array.unfreezeIfRegister(&self.register_manager);
......@@ -1597,7 +1597,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
15971597 .reg1 = addr_reg.to64(),
15981598 .reg2 = .rbp,
15991599 }).encode(),
1600 .data = .{ .imm = @bitCast(u32, -(off + @intCast(i32, array_abi_size))) },
1600 .data = .{ .imm = @bitCast(u32, -off) },
16011601 });
16021602 },
16031603 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
......@@ -1806,7 +1806,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
18061806 try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
18071807
18081808 return self.genInlineMemcpy(
1809 -(off + @intCast(i32, abi_size)),
1809 -off,
18101810 .rbp,
18111811 registerAlias(addr_reg, @divExact(reg.size(), 8)),
18121812 count_reg.to64(),
......@@ -2093,10 +2093,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
20932093 const mcv = try self.resolveInst(operand);
20942094 const ptr_ty = self.air.typeOf(operand);
20952095 const struct_ty = ptr_ty.childType();
2096 const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*));
20972096 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
2098 const struct_field_ty = struct_ty.structFieldType(index);
2099 const struct_field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*));
21002097
21012098 const dst_mcv: MCValue = result: {
21022099 switch (mcv) {
......@@ -2112,8 +2109,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
21122109 break :result dst_mcv;
21132110 },
21142111 .ptr_stack_offset => |off| {
2115 const offset_to_field = struct_size - struct_field_offset - struct_field_size;
2116 const ptr_stack_offset = off + @intCast(i32, offset_to_field);
2112 const ptr_stack_offset = off - @intCast(i32, struct_field_offset);
21172113 break :result MCValue{ .ptr_stack_offset = ptr_stack_offset };
21182114 },
21192115 .register => |reg| {
......@@ -2153,15 +2149,12 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
21532149 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
21542150 const mcv = try self.resolveInst(operand);
21552151 const struct_ty = self.air.typeOf(operand);
2156 const struct_size = struct_ty.abiSize(self.target.*);
21572152 const struct_field_offset = struct_ty.structFieldOffset(index, self.target.*);
21582153 const struct_field_ty = struct_ty.structFieldType(index);
2159 const struct_field_size = struct_field_ty.abiSize(self.target.*);
21602154
21612155 switch (mcv) {
21622156 .stack_offset => |off| {
2163 const offset_to_field = struct_size - struct_field_offset - struct_field_size;
2164 const stack_offset = off + @intCast(i32, offset_to_field);
2157 const stack_offset = off - @intCast(i32, struct_field_offset);
21652158 break :result MCValue{ .stack_offset = stack_offset };
21662159 },
21672160 .register => |reg| {
......@@ -2369,7 +2362,6 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC
23692362 if (off > math.maxInt(i32)) {
23702363 return self.fail("stack offset too large", .{});
23712364 }
2372 const adj_off = off + @intCast(i32, abi_size);
23732365 _ = try self.addInst(.{
23742366 .tag = mir_tag,
23752367 .ops = (Mir.Ops{
......@@ -2377,7 +2369,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC
23772369 .reg2 = .rbp,
23782370 .flags = 0b01,
23792371 }).encode(),
2380 .data = .{ .imm = @bitCast(u32, -adj_off) },
2372 .data = .{ .imm = @bitCast(u32, -off) },
23812373 });
23822374 },
23832375 .compare_flags_unsigned => {
......@@ -2395,7 +2387,6 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC
23952387 if (abi_size > 8) {
23962388 return self.fail("TODO implement ADD/SUB/CMP for stack dst with large ABI", .{});
23972389 }
2398 const adj_off = off + @intCast(i32, abi_size);
23992390
24002391 switch (src_mcv) {
24012392 .none => unreachable,
......@@ -2411,7 +2402,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC
24112402 .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),
24122403 .flags = 0b10,
24132404 }).encode(),
2414 .data = .{ .imm = @bitCast(u32, -adj_off) },
2405 .data = .{ .imm = @bitCast(u32, -off) },
24152406 });
24162407 },
24172408 .immediate => |imm| {
......@@ -2432,7 +2423,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC
24322423 else => unreachable,
24332424 };
24342425 const payload = try self.addExtra(Mir.ImmPair{
2435 .dest_off = @bitCast(u32, -adj_off),
2426 .dest_off = @bitCast(u32, -off),
24362427 .operand = @truncate(u32, imm),
24372428 });
24382429 _ = try self.addInst(.{
......@@ -2583,9 +2574,16 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
25832574 self.arg_index += 1;
25842575
25852576 const mcv = self.args[arg_index];
2577 const max_stack = loop: for (self.args) |arg| {
2578 switch (arg) {
2579 .stack_offset => |last| break :loop last,
2580 else => {},
2581 }
2582 } else 0;
25862583 const payload = try self.addExtra(Mir.ArgDbgInfo{
25872584 .air_inst = inst,
25882585 .arg_index = arg_index,
2586 .max_stack = @intCast(u32, max_stack),
25892587 });
25902588 _ = try self.addInst(.{
25912589 .tag = .arg_dbg_info,
......@@ -2601,11 +2599,9 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
26012599 self.register_manager.getRegAssumeFree(reg.to64(), inst);
26022600 break :blk mcv;
26032601 },
2604 .stack_offset => {
2605 const ty = self.air.typeOfIndex(inst);
2606 const abi_size = ty.abiSize(self.target.*);
2607 const off = @intCast(i32, (arg_index + 1) * abi_size) + 16;
2608 break :blk MCValue{ .stack_offset = -off };
2602 .stack_offset => |off| {
2603 const offset = max_stack - off + 16;
2604 break :blk MCValue{ .stack_offset = -offset };
26092605 },
26102606 else => return self.fail("TODO implement arg for {}", .{mcv}),
26112607 }
......@@ -2648,7 +2644,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
26482644 var info = try self.resolveCallingConventionValues(fn_ty);
26492645 defer info.deinit(self);
26502646
2651 var stack_adjustment: u32 = 0;
2647 var stack_adjustment: ?u32 = null;
26522648 for (args) |arg, arg_i| {
26532649 const mc_arg = info.args[arg_i];
26542650 const arg_ty = self.air.typeOf(arg);
......@@ -2662,9 +2658,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
26622658 try self.genSetReg(arg_ty, reg, arg_mcv);
26632659 },
26642660 .stack_offset => |off| {
2665 const abi_size = @intCast(u32, arg_ty.abiSize(self.target.*));
26662661 try self.genSetStackArg(arg_ty, off, arg_mcv);
2667 stack_adjustment += abi_size;
2662 if (stack_adjustment == null) {
2663 stack_adjustment = @intCast(u32, off);
2664 }
26682665 },
26692666 .ptr_stack_offset => {
26702667 return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{});
......@@ -2685,14 +2682,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
26852682 }
26862683 }
26872684
2688 if (stack_adjustment > 0) {
2685 if (stack_adjustment) |off| {
26892686 // Adjust the stack
26902687 _ = try self.addInst(.{
26912688 .tag = .sub,
26922689 .ops = (Mir.Ops{
26932690 .reg1 = .rsp,
26942691 }).encode(),
2695 .data = .{ .imm = stack_adjustment },
2692 .data = .{ .imm = off },
26962693 });
26972694 }
26982695
......@@ -2820,14 +2817,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
28202817 }
28212818 } else unreachable;
28222819
2823 if (stack_adjustment > 0) {
2820 if (stack_adjustment) |off| {
28242821 // Readjust the stack
28252822 _ = try self.addInst(.{
28262823 .tag = .add,
28272824 .ops = (Mir.Ops{
28282825 .reg1 = .rsp,
28292826 }).encode(),
2830 .data = .{ .imm = stack_adjustment },
2827 .data = .{ .imm = off },
28312828 });
28322829 }
28332830
......@@ -3583,14 +3580,13 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
35833580 return self.genSetStackArg(ty, stack_offset, .{ .register = reg });
35843581 },
35853582 .immediate => |imm| {
3586 const off = stack_offset + @intCast(i32, abi_size);
35873583 switch (abi_size) {
35883584 1, 2, 4 => {
35893585 // We have a positive stack offset value but we want a twos complement negative
35903586 // offset from rbp, which is at the top of the stack frame.
35913587 // mov [rbp+offset], immediate
35923588 const payload = try self.addExtra(Mir.ImmPair{
3593 .dest_off = @bitCast(u32, -off),
3589 .dest_off = @bitCast(u32, -stack_offset),
35943590 .operand = @truncate(u32, imm),
35953591 });
35963592 _ = try self.addInst(.{
......@@ -3680,7 +3676,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
36803676 // TODO allow for abi_size to be u64
36813677 try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
36823678 try self.genInlineMemcpy(
3683 -(stack_offset + @intCast(i32, abi_size)),
3679 -stack_offset,
36843680 .rsp,
36853681 addr_reg.to64(),
36863682 count_reg.to64(),
......@@ -3695,14 +3691,14 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
36953691 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),
36963692 .flags = 0b10,
36973693 }).encode(),
3698 .data = .{ .imm = @bitCast(u32, -(stack_offset + @intCast(i32, abi_size))) },
3694 .data = .{ .imm = @bitCast(u32, -stack_offset) },
36993695 });
37003696 },
37013697 .ptr_stack_offset => {
37023698 const reg = try self.copyToTmpRegister(ty, mcv);
37033699 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
37043700 },
3705 .stack_offset => |unadjusted_off| {
3701 .stack_offset => |off| {
37063702 if (abi_size <= 8) {
37073703 const reg = try self.copyToTmpRegister(ty, mcv);
37083704 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
......@@ -3725,13 +3721,13 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
37253721 .reg1 = addr_reg.to64(),
37263722 .reg2 = .rbp,
37273723 }).encode(),
3728 .data = .{ .imm = @bitCast(u32, -(unadjusted_off + @intCast(i32, abi_size))) },
3724 .data = .{ .imm = @bitCast(u32, -off) },
37293725 });
37303726
37313727 // TODO allow for abi_size to be u64
37323728 try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
37333729 try self.genInlineMemcpy(
3734 -(stack_offset + @intCast(i32, abi_size)),
3730 -stack_offset,
37353731 .rsp,
37363732 addr_reg.to64(),
37373733 count_reg.to64(),
......@@ -3767,17 +3763,13 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
37673763 return self.genSetStack(ty, stack_offset, .{ .register = reg });
37683764 },
37693765 .immediate => |x_big| {
3770 const adj_off = stack_offset + @intCast(i32, abi_size);
3771 if (adj_off > 128) {
3766 if (stack_offset > 128) {
37723767 return self.fail("TODO implement set stack variable with large stack offset", .{});
37733768 }
37743769 switch (abi_size) {
37753770 1, 2, 4 => {
3776 // We have a positive stack offset value but we want a twos complement negative
3777 // offset from rbp, which is at the top of the stack frame.
3778 // mov [rbp+offset], immediate
37793771 const payload = try self.addExtra(Mir.ImmPair{
3780 .dest_off = @bitCast(u32, -adj_off),
3772 .dest_off = @bitCast(u32, -stack_offset),
37813773 .operand = @truncate(u32, x_big),
37823774 });
37833775 _ = try self.addInst(.{
......@@ -3795,15 +3787,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
37953787 });
37963788 },
37973789 8 => {
3798 // We have a positive stack offset value but we want a twos complement negative
3799 // offset from rbp, which is at the top of the stack frame.
3800 const negative_offset = -adj_off;
3801
38023790 // 64 bit write to memory would take two mov's anyways so we
38033791 // insted just use two 32 bit writes to avoid register allocation
38043792 {
38053793 const payload = try self.addExtra(Mir.ImmPair{
3806 .dest_off = @bitCast(u32, negative_offset + 4),
3794 .dest_off = @bitCast(u32, -stack_offset + 4),
38073795 .operand = @truncate(u32, x_big >> 32),
38083796 });
38093797 _ = try self.addInst(.{
......@@ -3817,7 +3805,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
38173805 }
38183806 {
38193807 const payload = try self.addExtra(Mir.ImmPair{
3820 .dest_off = @bitCast(u32, negative_offset),
3808 .dest_off = @bitCast(u32, -stack_offset),
38213809 .operand = @truncate(u32, x_big),
38223810 });
38233811 _ = try self.addInst(.{
......@@ -3839,7 +3827,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
38393827 if (stack_offset > math.maxInt(i32)) {
38403828 return self.fail("stack offset too large", .{});
38413829 }
3842 const adj_off = stack_offset + @intCast(i32, abi_size);
38433830 _ = try self.addInst(.{
38443831 .tag = .mov,
38453832 .ops = (Mir.Ops{
......@@ -3847,7 +3834,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
38473834 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),
38483835 .flags = 0b10,
38493836 }).encode(),
3850 .data = .{ .imm = @bitCast(u32, -adj_off) },
3837 .data = .{ .imm = @bitCast(u32, -stack_offset) },
38513838 });
38523839 },
38533840 .memory,
......@@ -3913,7 +3900,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
39133900 try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
39143901
39153902 return self.genInlineMemcpy(
3916 -(stack_offset + @intCast(i32, abi_size)),
3903 -stack_offset,
39173904 .rbp,
39183905 addr_reg.to64(),
39193906 count_reg.to64(),
......@@ -3952,14 +3939,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
39523939 .reg1 = addr_reg.to64(),
39533940 .reg2 = .rbp,
39543941 }).encode(),
3955 .data = .{ .imm = @bitCast(u32, -(off + @intCast(i32, abi_size))) },
3942 .data = .{ .imm = @bitCast(u32, -off) },
39563943 });
39573944
39583945 // TODO allow for abi_size to be u64
39593946 try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
39603947
39613948 return self.genInlineMemcpy(
3962 -(stack_offset + @intCast(i32, abi_size)),
3949 -stack_offset,
39633950 .rbp,
39643951 addr_reg.to64(),
39653952 count_reg.to64(),
......@@ -4073,11 +4060,10 @@ fn genInlineMemcpy(
40734060fn genInlineMemset(self: *Self, ty: Type, stack_offset: i32, value: MCValue) InnerError!void {
40744061 try self.register_manager.getReg(.rax, null);
40754062 const abi_size = ty.abiSize(self.target.*);
4076 const adj_off = stack_offset + @intCast(i32, abi_size);
4077 if (adj_off > 128) {
4063 if (stack_offset > 128) {
40784064 return self.fail("TODO inline memset with large stack offset", .{});
40794065 }
4080 const negative_offset = @bitCast(u32, -adj_off);
4066 const negative_offset = @bitCast(u32, -stack_offset);
40814067
40824068 // We are actually counting `abi_size` bytes; however, we reuse the index register
40834069 // as both the counter and offset scaler, hence we need to subtract one from `abi_size`
......@@ -4165,10 +4151,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
41654151 const abi_size = ty.abiSize(self.target.*);
41664152 switch (mcv) {
41674153 .dead => unreachable,
4168 .ptr_stack_offset => |unadjusted_off| {
4169 const elem_ty = ty.childType();
4170 const elem_abi_size = elem_ty.abiSize(self.target.*);
4171 const off = unadjusted_off + @intCast(i32, elem_abi_size);
4154 .ptr_stack_offset => |off| {
41724155 if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) {
41734156 return self.fail("stack offset too large", .{});
41744157 }
......@@ -4391,8 +4374,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
43914374 }
43924375 }
43934376 },
4394 .stack_offset => |unadjusted_off| {
4395 const off = unadjusted_off + @intCast(i32, abi_size);
4377 .stack_offset => |off| {
43964378 if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) {
43974379 return self.fail("stack offset too large", .{});
43984380 }
......@@ -4469,8 +4451,8 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
44694451 const array_len = array_ty.arrayLenIncludingSentinel();
44704452 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
44714453 const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16));
4472 try self.genSetStack(ptr_ty, stack_offset + 8, ptr);
4473 try self.genSetStack(Type.initTag(.u64), stack_offset, .{ .immediate = array_len });
4454 try self.genSetStack(ptr_ty, stack_offset, ptr);
4455 try self.genSetStack(Type.initTag(.u64), stack_offset - 8, .{ .immediate = array_len });
44744456 break :blk .{ .stack_offset = stack_offset };
44754457 };
44764458 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -4883,7 +4865,6 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
48834865 var next_stack_offset: u32 = 0;
48844866 var count: usize = param_types.len;
48854867 while (count > 0) : (count -= 1) {
4886 // for (param_types) |ty, i| {
48874868 const i = count - 1;
48884869 const ty = param_types[i];
48894870 if (!ty.hasRuntimeBits()) {
......@@ -4892,6 +4873,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
48924873 continue;
48934874 }
48944875 const param_size = @intCast(u32, ty.abiSize(self.target.*));
4876 const param_align = @intCast(u32, ty.abiAlignment(self.target.*));
48954877 if (by_reg.get(i)) |int_reg| {
48964878 const aliased_reg = registerAlias(c_abi_int_param_regs[int_reg], param_size);
48974879 result.args[i] = .{ .register = aliased_reg };
......@@ -4902,8 +4884,9 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
49024884 // such as ptr and len of slices as separate registers.
49034885 // TODO: also we need to honor the C ABI for relevant types rather than passing on
49044886 // the stack here.
4905 result.args[i] = .{ .stack_offset = @intCast(i32, next_stack_offset) };
4906 next_stack_offset += param_size;
4887 const offset = mem.alignForwardGeneric(u32, next_stack_offset + param_size, param_align);
4888 result.args[i] = .{ .stack_offset = @intCast(i32, offset) };
4889 next_stack_offset = offset;
49074890 }
49084891 }
49094892
src/arch/x86_64/Emit.zig+4-5
......@@ -931,16 +931,15 @@ fn mirArgDbgInfo(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
931931 const payload = emit.mir.instructions.items(.data)[inst].payload;
932932 const arg_dbg_info = emit.mir.extraData(Mir.ArgDbgInfo, payload).data;
933933 const mcv = emit.mir.function.args[arg_dbg_info.arg_index];
934 try emit.genArgDbgInfo(arg_dbg_info.air_inst, mcv, arg_dbg_info.arg_index);
934 try emit.genArgDbgInfo(arg_dbg_info.air_inst, mcv, arg_dbg_info.max_stack);
935935}
936936
937fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) !void {
937fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32) !void {
938938 const ty_str = emit.mir.function.air.instructions.items(.data)[inst].ty_str;
939939 const zir = &emit.mir.function.mod_fn.owner_decl.getFileScope().zir;
940940 const name = zir.nullTerminatedString(ty_str.str);
941941 const name_with_null = name.ptr[0 .. name.len + 1];
942942 const ty = emit.mir.function.air.getRefType(ty_str.ty);
943 const abi_size = ty.abiSize(emit.bin_file.options.target);
944943
945944 switch (mcv) {
946945 .register => |reg| {
......@@ -960,7 +959,7 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32
960959 .none => {},
961960 }
962961 },
963 .stack_offset => {
962 .stack_offset => |off| {
964963 switch (emit.debug_output) {
965964 .dwarf => |dbg_out| {
966965 // we add here +16 like we do in airArg in CodeGen since we refer directly to
......@@ -968,7 +967,7 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32
968967 // prologue, and 8 bytes for return address.
969968 // TODO we need to make this more generic if we don't use rbp as the frame pointer
970969 // for example when -fomit-frame-pointer is set.
971 const disp = @intCast(i32, arg_index * abi_size + 16);
970 const disp = @intCast(i32, max_stack) - off + 16;
972971 try dbg_out.dbg_info.ensureUnusedCapacity(8);
973972 dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
974973 const fixup = dbg_out.dbg_info.items.len;
src/arch/x86_64/Mir.zig+1
......@@ -413,6 +413,7 @@ pub const DbgLineColumn = struct {
413413pub const ArgDbgInfo = struct {
414414 air_inst: Air.Inst.Index,
415415 arg_index: u32,
416 max_stack: u32,
416417};
417418
418419pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {