Skip to content

Commit 4c51565

Browse files
stage2 ARM: pass stack arguments in opposite order
Earlier arguments have a smaller address (i.e. towards the bottom of the stack)
1 parent 7e07f3d commit 4c51565

File tree

2 files changed

+34
-51
lines changed

2 files changed

+34
-51
lines changed

src/arch/arm/CodeGen.zig

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ pub fn generate(
332332
};
333333

334334
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);
336336
}
337337

338338
var mir = Mir{
@@ -351,7 +351,8 @@ pub fn generate(
351351
.prev_di_pc = 0,
352352
.prev_di_line = module_fn.lbrace_line,
353353
.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,
355356
};
356357
defer emit.deinit();
357358

@@ -464,6 +465,7 @@ fn gen(self: *Self) !void {
464465
const total_stack_size = self.max_end_stack + self.saved_regs_stack_space;
465466
const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align);
466467
const stack_size = aligned_total_stack_end - self.saved_regs_stack_space;
468+
self.max_end_stack = stack_size;
467469
if (Instruction.Operand.fromU32(stack_size)) |op| {
468470
self.mir_instructions.set(sub_reloc, .{
469471
.tag = .sub,
@@ -1812,7 +1814,7 @@ fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCV
18121814
switch (error_union_mcv) {
18131815
.register => return self.fail("TODO errUnionErr for registers", .{}),
18141816
.stack_argument_offset => |off| {
1815-
return MCValue{ .stack_argument_offset = off - err_offset };
1817+
return MCValue{ .stack_argument_offset = off + err_offset };
18161818
},
18171819
.stack_offset => |off| {
18181820
return MCValue{ .stack_offset = off - err_offset };
@@ -1849,7 +1851,7 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type)
18491851
switch (error_union_mcv) {
18501852
.register => return self.fail("TODO errUnionPayload for registers", .{}),
18511853
.stack_argument_offset => |off| {
1852-
return MCValue{ .stack_argument_offset = off - payload_offset };
1854+
return MCValue{ .stack_argument_offset = off + payload_offset };
18531855
},
18541856
.stack_offset => |off| {
18551857
return MCValue{ .stack_offset = off - payload_offset };
@@ -1983,7 +1985,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
19831985
.dead, .unreach => unreachable,
19841986
.register => unreachable, // a slice doesn't fit in one register
19851987
.stack_argument_offset => |off| {
1986-
break :result MCValue{ .stack_argument_offset = off - 4 };
1988+
break :result MCValue{ .stack_argument_offset = off + 4 };
19871989
},
19881990
.stack_offset => |off| {
19891991
break :result MCValue{ .stack_offset = off - 4 };
@@ -2507,7 +2509,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
25072509
switch (mcv) {
25082510
.dead, .unreach => unreachable,
25092511
.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 };
25112513
},
25122514
.stack_offset => |off| {
25132515
break :result MCValue{ .stack_offset = off - struct_field_offset };
@@ -3369,9 +3371,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void {
33693371
}
33703372
}
33713373

3372-
fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32, stack_byte_count: u32) error{OutOfMemory}!void {
3373-
const prologue_stack_space = stack_byte_count + self.saved_regs_stack_space;
3374-
3374+
fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfMemory}!void {
33753375
const mcv = self.args[arg_index];
33763376
const ty = self.air.instructions.items(.data)[inst].ty;
33773377
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
34043404
// const abi_size = @intCast(u32, ty.abiSize(self.target.*));
34053405
const adjusted_stack_offset = switch (mcv) {
34063406
.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),
34083408
else => unreachable,
34093409
};
34103410

@@ -3559,7 +3559,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
35593559
.stack_offset => unreachable,
35603560
.stack_argument_offset => |offset| try self.genSetStackArgument(
35613561
arg_ty,
3562-
info.stack_byte_count - offset,
3562+
offset,
35633563
arg_mcv,
35643564
),
35653565
else => unreachable,
@@ -5653,8 +5653,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
56535653
if (ty.abiAlignment(self.target.*) == 8)
56545654
nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);
56555655

5656-
nsaa += param_size;
56575656
result.args[i] = .{ .stack_argument_offset = nsaa };
5657+
nsaa += param_size;
56585658
}
56595659
}
56605660

@@ -5687,9 +5687,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
56875687
for (param_types) |ty, i| {
56885688
if (ty.abiSize(self.target.*) > 0) {
56895689
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);
56925693
result.args[i] = .{ .stack_argument_offset = stack_offset };
5694+
stack_offset += param_size;
56935695
} else {
56945696
result.args[i] = .{ .none = {} };
56955697
}

src/arch/arm/Emit.zig

Lines changed: 19 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,13 @@ prev_di_column: u32,
3333
/// Relative to the beginning of `code`.
3434
prev_di_pc: usize,
3535

36-
/// The amount of stack space consumed by all stack arguments as well
37-
/// as the saved callee-saved registers
38-
prologue_stack_space: u32,
36+
/// The amount of stack space consumed by the saved callee-saved
37+
/// registers in bytes
38+
saved_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.
42+
stack_size: u32,
3943

4044
/// The branch type of every branch
4145
branch_types: std.AutoHashMapUnmanaged(Mir.Inst.Index, BranchType) = .{},
@@ -500,14 +504,15 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
500504
const tag = emit.mir.instructions.items(.tag)[inst];
501505
const cond = emit.mir.instructions.items(.cond)[inst];
502506
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;
505510
switch (tag) {
506511
.ldr_ptr_stack_argument => {
507512
const operand = Instruction.Operand.fromU32(raw_offset) orelse
508513
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));
511516
},
512517
.ldr_stack_argument,
513518
.ldrb_stack_argument,
@@ -516,23 +521,11 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
516521
break :blk Instruction.Offset.imm(@intCast(u12, raw_offset));
517522
} else return emit.fail("TODO mirLoadStack larger offsets", .{});
518523

519-
const ldr = switch (tag) {
520-
.ldr_stack_argument => &Instruction.ldr,
521-
.ldrb_stack_argument => &Instruction.ldrb,
524+
switch (tag) {
525+
.ldr_stack_argument => try emit.writeInstruction(Instruction.ldr(cond, rt, .sp, .{ .offset = offset })),
526+
.ldrb_stack_argument => try emit.writeInstruction(Instruction.ldrb(cond, rt, .sp, .{ .offset = offset })),
522527
else => unreachable,
523-
};
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-
));
528+
}
536529
},
537530
.ldrh_stack_argument,
538531
.ldrsb_stack_argument,
@@ -542,24 +535,12 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
542535
break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, raw_offset));
543536
} else return emit.fail("TODO mirLoadStack larger offsets", .{});
544537

545-
const ldr = switch (tag) {
546-
.ldrh_stack_argument => &Instruction.ldrh,
547-
.ldrsb_stack_argument => &Instruction.ldrsb,
548-
.ldrsh_stack_argument => &Instruction.ldrsh,
538+
switch (tag) {
539+
.ldrh_stack_argument => try emit.writeInstruction(Instruction.ldrh(cond, rt, .sp, .{ .offset = offset })),
540+
.ldrsb_stack_argument => try emit.writeInstruction(Instruction.ldrsb(cond, rt, .sp, .{ .offset = offset })),
541+
.ldrsh_stack_argument => try emit.writeInstruction(Instruction.ldrsh(cond, rt, .sp, .{ .offset = offset })),
549542
else => unreachable,
550-
};
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-
));
543+
}
563544
},
564545
else => unreachable,
565546
}

0 commit comments

Comments
 (0)