authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-06 21:23:21+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-13 17:00:00+02:00
log4c5156544b1b96a4860f98ecac5c7abe47de5465
treec218f36fe752e2d1e4227500f862851be3a31797
parent7e07f3d4f95f9e7a0d95ee7b9335798eccb470c7
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: pass stack arguments in opposite order

Earlier arguments have a smaller address (i.e. towards the bottom of the stack)

2 files changed, 34 insertions(+), 51 deletions(-)

src/arch/arm/CodeGen.zig+15-13
...@@ -332,7 +332,7 @@ pub fn generate(...@@ -332,7 +332,7 @@ pub fn generate(
332 };332 };
333333
334 for (function.dbg_arg_relocs.items) |reloc| {334 for (function.dbg_arg_relocs.items) |reloc| {
335 try function.genArgDbgInfo(reloc.inst, reloc.index, call_info.stack_byte_count);335 try function.genArgDbgInfo(reloc.inst, reloc.index);
336 }336 }
337337
338 var mir = Mir{338 var mir = Mir{
...@@ -351,7 +351,8 @@ pub fn generate(...@@ -351,7 +351,8 @@ pub fn generate(
351 .prev_di_pc = 0,351 .prev_di_pc = 0,
352 .prev_di_line = module_fn.lbrace_line,352 .prev_di_line = module_fn.lbrace_line,
353 .prev_di_column = module_fn.lbrace_column,353 .prev_di_column = module_fn.lbrace_column,
354 .prologue_stack_space = call_info.stack_byte_count + function.saved_regs_stack_space,354 .stack_size = function.max_end_stack,
355 .saved_regs_stack_space = function.saved_regs_stack_space,
355 };356 };
356 defer emit.deinit();357 defer emit.deinit();
357358
...@@ -464,6 +465,7 @@ fn gen(self: *Self) !void {...@@ -464,6 +465,7 @@ fn gen(self: *Self) !void {
464 const total_stack_size = self.max_end_stack + self.saved_regs_stack_space;465 const total_stack_size = self.max_end_stack + self.saved_regs_stack_space;
465 const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align);466 const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align);
466 const stack_size = aligned_total_stack_end - self.saved_regs_stack_space;467 const stack_size = aligned_total_stack_end - self.saved_regs_stack_space;
468 self.max_end_stack = stack_size;
467 if (Instruction.Operand.fromU32(stack_size)) |op| {469 if (Instruction.Operand.fromU32(stack_size)) |op| {
468 self.mir_instructions.set(sub_reloc, .{470 self.mir_instructions.set(sub_reloc, .{
469 .tag = .sub,471 .tag = .sub,
...@@ -1812,7 +1814,7 @@ fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCV...@@ -1812,7 +1814,7 @@ fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCV
1812 switch (error_union_mcv) {1814 switch (error_union_mcv) {
1813 .register => return self.fail("TODO errUnionErr for registers", .{}),1815 .register => return self.fail("TODO errUnionErr for registers", .{}),
1814 .stack_argument_offset => |off| {1816 .stack_argument_offset => |off| {
1815 return MCValue{ .stack_argument_offset = off - err_offset };1817 return MCValue{ .stack_argument_offset = off + err_offset };
1816 },1818 },
1817 .stack_offset => |off| {1819 .stack_offset => |off| {
1818 return MCValue{ .stack_offset = off - err_offset };1820 return MCValue{ .stack_offset = off - err_offset };
...@@ -1849,7 +1851,7 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type)...@@ -1849,7 +1851,7 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type)
1849 switch (error_union_mcv) {1851 switch (error_union_mcv) {
1850 .register => return self.fail("TODO errUnionPayload for registers", .{}),1852 .register => return self.fail("TODO errUnionPayload for registers", .{}),
1851 .stack_argument_offset => |off| {1853 .stack_argument_offset => |off| {
1852 return MCValue{ .stack_argument_offset = off - payload_offset };1854 return MCValue{ .stack_argument_offset = off + payload_offset };
1853 },1855 },
1854 .stack_offset => |off| {1856 .stack_offset => |off| {
1855 return MCValue{ .stack_offset = off - payload_offset };1857 return MCValue{ .stack_offset = off - payload_offset };
...@@ -1983,7 +1985,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -1983,7 +1985,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
1983 .dead, .unreach => unreachable,1985 .dead, .unreach => unreachable,
1984 .register => unreachable, // a slice doesn't fit in one register1986 .register => unreachable, // a slice doesn't fit in one register
1985 .stack_argument_offset => |off| {1987 .stack_argument_offset => |off| {
1986 break :result MCValue{ .stack_argument_offset = off - 4 };1988 break :result MCValue{ .stack_argument_offset = off + 4 };
1987 },1989 },
1988 .stack_offset => |off| {1990 .stack_offset => |off| {
1989 break :result MCValue{ .stack_offset = off - 4 };1991 break :result MCValue{ .stack_offset = off - 4 };
...@@ -2507,7 +2509,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2507,7 +2509,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2507 switch (mcv) {2509 switch (mcv) {
2508 .dead, .unreach => unreachable,2510 .dead, .unreach => unreachable,
2509 .stack_argument_offset => |off| {2511 .stack_argument_offset => |off| {
2510 break :result MCValue{ .stack_argument_offset = off - struct_field_offset };2512 break :result MCValue{ .stack_argument_offset = off + struct_field_offset };
2511 },2513 },
2512 .stack_offset => |off| {2514 .stack_offset => |off| {
2513 break :result MCValue{ .stack_offset = off - struct_field_offset };2515 break :result MCValue{ .stack_offset = off - struct_field_offset };
...@@ -3369,9 +3371,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void {...@@ -3369,9 +3371,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void {
3369 }3371 }
3370}3372}
33713373
3372fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32, stack_byte_count: u32) error{OutOfMemory}!void {3374fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfMemory}!void {
3373 const prologue_stack_space = stack_byte_count + self.saved_regs_stack_space;
3374
3375 const mcv = self.args[arg_index];3375 const mcv = self.args[arg_index];
3376 const ty = self.air.instructions.items(.data)[inst].ty;3376 const ty = self.air.instructions.items(.data)[inst].ty;
3377 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index);3377 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index);
...@@ -3404,7 +3404,7 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32, stack_byte_c...@@ -3404,7 +3404,7 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32, stack_byte_c
3404 // const abi_size = @intCast(u32, ty.abiSize(self.target.*));3404 // const abi_size = @intCast(u32, ty.abiSize(self.target.*));
3405 const adjusted_stack_offset = switch (mcv) {3405 const adjusted_stack_offset = switch (mcv) {
3406 .stack_offset => |offset| -@intCast(i32, offset),3406 .stack_offset => |offset| -@intCast(i32, offset),
3407 .stack_argument_offset => |offset| @intCast(i32, prologue_stack_space - offset),3407 .stack_argument_offset => |offset| @intCast(i32, self.saved_regs_stack_space + offset),
3408 else => unreachable,3408 else => unreachable,
3409 };3409 };
34103410
...@@ -3559,7 +3559,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -3559,7 +3559,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
3559 .stack_offset => unreachable,3559 .stack_offset => unreachable,
3560 .stack_argument_offset => |offset| try self.genSetStackArgument(3560 .stack_argument_offset => |offset| try self.genSetStackArgument(
3561 arg_ty,3561 arg_ty,
3562 info.stack_byte_count - offset,3562 offset,
3563 arg_mcv,3563 arg_mcv,
3564 ),3564 ),
3565 else => unreachable,3565 else => unreachable,
...@@ -5653,8 +5653,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -5653,8 +5653,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
5653 if (ty.abiAlignment(self.target.*) == 8)5653 if (ty.abiAlignment(self.target.*) == 8)
5654 nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);5654 nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);
56555655
5656 nsaa += param_size;
5657 result.args[i] = .{ .stack_argument_offset = nsaa };5656 result.args[i] = .{ .stack_argument_offset = nsaa };
5657 nsaa += param_size;
5658 }5658 }
5659 }5659 }
56605660
...@@ -5687,9 +5687,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -5687,9 +5687,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
5687 for (param_types) |ty, i| {5687 for (param_types) |ty, i| {
5688 if (ty.abiSize(self.target.*) > 0) {5688 if (ty.abiSize(self.target.*) > 0) {
5689 const param_size = @intCast(u32, ty.abiSize(self.target.*));5689 const param_size = @intCast(u32, ty.abiSize(self.target.*));
5690 const param_alignment = ty.abiAlignment(self.target.*);
56905691
5691 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, ty.abiAlignment(self.target.*)) + param_size;5692 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);
5692 result.args[i] = .{ .stack_argument_offset = stack_offset };5693 result.args[i] = .{ .stack_argument_offset = stack_offset };
5694 stack_offset += param_size;
5693 } else {5695 } else {
5694 result.args[i] = .{ .none = {} };5696 result.args[i] = .{ .none = {} };
5695 }5697 }
src/arch/arm/Emit.zig+19-38
...@@ -33,9 +33,13 @@ prev_di_column: u32,...@@ -33,9 +33,13 @@ prev_di_column: u32,
33/// Relative to the beginning of `code`.33/// Relative to the beginning of `code`.
34prev_di_pc: usize,34prev_di_pc: usize,
3535
36/// The amount of stack space consumed by all stack arguments as well36/// The amount of stack space consumed by the saved callee-saved
37/// as the saved callee-saved registers37/// registers in bytes
38prologue_stack_space: u32,38saved_regs_stack_space: u32,
39
40/// The final stack frame size of the function (already aligned to the
41/// respective stack alignment). Does not include prologue stack space.
42stack_size: u32,
3943
40/// The branch type of every branch44/// The branch type of every branch
41branch_types: std.AutoHashMapUnmanaged(Mir.Inst.Index, BranchType) = .{},45branch_types: std.AutoHashMapUnmanaged(Mir.Inst.Index, BranchType) = .{},
...@@ -500,14 +504,15 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -500,14 +504,15 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
500 const tag = emit.mir.instructions.items(.tag)[inst];504 const tag = emit.mir.instructions.items(.tag)[inst];
501 const cond = emit.mir.instructions.items(.cond)[inst];505 const cond = emit.mir.instructions.items(.cond)[inst];
502 const r_stack_offset = emit.mir.instructions.items(.data)[inst].r_stack_offset;506 const r_stack_offset = emit.mir.instructions.items(.data)[inst].r_stack_offset;
507 const rt = r_stack_offset.rt;
503508
504 const raw_offset = emit.prologue_stack_space - r_stack_offset.stack_offset;509 const raw_offset = emit.stack_size + emit.saved_regs_stack_space + r_stack_offset.stack_offset;
505 switch (tag) {510 switch (tag) {
506 .ldr_ptr_stack_argument => {511 .ldr_ptr_stack_argument => {
507 const operand = Instruction.Operand.fromU32(raw_offset) orelse512 const operand = Instruction.Operand.fromU32(raw_offset) orelse
508 return emit.fail("TODO mirLoadStack larger offsets", .{});513 return emit.fail("TODO mirLoadStack larger offsets", .{});
509514
510 try emit.writeInstruction(Instruction.add(cond, r_stack_offset.rt, .fp, operand));515 try emit.writeInstruction(Instruction.add(cond, rt, .sp, operand));
511 },516 },
512 .ldr_stack_argument,517 .ldr_stack_argument,
513 .ldrb_stack_argument,518 .ldrb_stack_argument,
...@@ -516,23 +521,11 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -516,23 +521,11 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
516 break :blk Instruction.Offset.imm(@intCast(u12, raw_offset));521 break :blk Instruction.Offset.imm(@intCast(u12, raw_offset));
517 } else return emit.fail("TODO mirLoadStack larger offsets", .{});522 } else return emit.fail("TODO mirLoadStack larger offsets", .{});
518523
519 const ldr = switch (tag) {524 switch (tag) {
520 .ldr_stack_argument => &Instruction.ldr,525 .ldr_stack_argument => try emit.writeInstruction(Instruction.ldr(cond, rt, .sp, .{ .offset = offset })),
521 .ldrb_stack_argument => &Instruction.ldrb,526 .ldrb_stack_argument => try emit.writeInstruction(Instruction.ldrb(cond, rt, .sp, .{ .offset = offset })),
522 else => unreachable,527 else => unreachable,
523 };528 }
524
525 const ldr_workaround = switch (builtin.zig_backend) {
526 .stage1 => ldr.*,
527 else => ldr,
528 };
529
530 try emit.writeInstruction(ldr_workaround(
531 cond,
532 r_stack_offset.rt,
533 .fp,
534 .{ .offset = offset },
535 ));
536 },529 },
537 .ldrh_stack_argument,530 .ldrh_stack_argument,
538 .ldrsb_stack_argument,531 .ldrsb_stack_argument,
...@@ -542,24 +535,12 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -542,24 +535,12 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
542 break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, raw_offset));535 break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, raw_offset));
543 } else return emit.fail("TODO mirLoadStack larger offsets", .{});536 } else return emit.fail("TODO mirLoadStack larger offsets", .{});
544537
545 const ldr = switch (tag) {538 switch (tag) {
546 .ldrh_stack_argument => &Instruction.ldrh,539 .ldrh_stack_argument => try emit.writeInstruction(Instruction.ldrh(cond, rt, .sp, .{ .offset = offset })),
547 .ldrsb_stack_argument => &Instruction.ldrsb,540 .ldrsb_stack_argument => try emit.writeInstruction(Instruction.ldrsb(cond, rt, .sp, .{ .offset = offset })),
548 .ldrsh_stack_argument => &Instruction.ldrsh,541 .ldrsh_stack_argument => try emit.writeInstruction(Instruction.ldrsh(cond, rt, .sp, .{ .offset = offset })),
549 else => unreachable,542 else => unreachable,
550 };543 }
551
552 const ldr_workaround = switch (builtin.zig_backend) {
553 .stage1 => ldr.*,
554 else => ldr,
555 };
556
557 try emit.writeInstruction(ldr_workaround(
558 cond,
559 r_stack_offset.rt,
560 .fp,
561 .{ .offset = offset },
562 ));
563 },544 },
564 else => unreachable,545 else => unreachable,
565 }546 }