authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-09-04 22:28:59+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-09-09 19:17:18+02:00
loga0a7d15142cfffbab934860064a44b7615f9dd55
treea4cac7d9d5c78222581aadac1e2a001fa68bb330
parent3794f2c493c9744e19cd7df23c3d4b32565aaa96
signature Commit is signed but in an unrecognized format.

stage2 ARM: support larger function stacks

This is done by introducing a new Mir pseudo-instruction

4 files changed, 65 insertions(+), 9 deletions(-)

src/arch/arm/CodeGen.zig+4-8
......@@ -488,14 +488,10 @@ fn gen(self: *Self) !void {
488488 const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align);
489489 const stack_size = aligned_total_stack_end - self.saved_regs_stack_space;
490490 self.max_end_stack = stack_size;
491 if (Instruction.Operand.fromU32(stack_size)) |op| {
492 self.mir_instructions.set(sub_reloc, .{
493 .tag = .sub,
494 .data = .{ .rr_op = .{ .rd = .sp, .rn = .sp, .op = op } },
495 });
496 } else {
497 return self.failSymbol("TODO ARM: allow larger stacks", .{});
498 }
491 self.mir_instructions.set(sub_reloc, .{
492 .tag = .sub_sp_scratch_r0,
493 .data = .{ .imm32 = stack_size },
494 });
499495
500496 _ = try self.addInst(.{
501497 .tag = .dbg_epilogue_begin,
src/arch/arm/Emit.zig+52
......@@ -11,6 +11,7 @@ const link = @import("../../link.zig");
1111const Module = @import("../../Module.zig");
1212const Type = @import("../../type.zig").Type;
1313const ErrorMsg = Module.ErrorMsg;
14const Target = std.Target;
1415const assert = std.debug.assert;
1516const DW = std.dwarf;
1617const leb128 = std.leb;
......@@ -93,6 +94,8 @@ pub fn emitMir(
9394 .sub => try emit.mirDataProcessing(inst),
9495 .subs => try emit.mirDataProcessing(inst),
9596
97 .sub_sp_scratch_r0 => try emit.mirSubStackPointer(inst),
98
9699 .asr => try emit.mirShift(inst),
97100 .lsl => try emit.mirShift(inst),
98101 .lsr => try emit.mirShift(inst),
......@@ -190,6 +193,24 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {
190193 .dbg_epilogue_begin,
191194 .dbg_prologue_end,
192195 => return 0,
196
197 .sub_sp_scratch_r0 => {
198 const imm32 = emit.mir.instructions.items(.data)[inst].imm32;
199
200 if (imm32 == 0) {
201 return 0 * 4;
202 } else if (Instruction.Operand.fromU32(imm32) != null) {
203 // sub
204 return 1 * 4;
205 } else if (Target.arm.featureSetHas(emit.target.cpu.features, .has_v7)) {
206 // movw; movt; sub
207 return 3 * 4;
208 } else {
209 // mov; orr; orr; orr; sub
210 return 5 * 4;
211 }
212 },
213
193214 else => return 4,
194215 }
195216}
......@@ -427,6 +448,37 @@ fn mirDataProcessing(emit: *Emit, inst: Mir.Inst.Index) !void {
427448 }
428449}
429450
451fn mirSubStackPointer(emit: *Emit, inst: Mir.Inst.Index) !void {
452 const tag = emit.mir.instructions.items(.tag)[inst];
453 const cond = emit.mir.instructions.items(.cond)[inst];
454 const imm32 = emit.mir.instructions.items(.data)[inst].imm32;
455
456 switch (tag) {
457 .sub_sp_scratch_r0 => {
458 if (imm32 == 0) return;
459
460 const operand = Instruction.Operand.fromU32(imm32) orelse blk: {
461 const scratch: Register = .r0;
462
463 if (Target.arm.featureSetHas(emit.target.cpu.features, .has_v7)) {
464 try emit.writeInstruction(Instruction.movw(cond, scratch, @truncate(u16, imm32)));
465 try emit.writeInstruction(Instruction.movt(cond, scratch, @truncate(u16, imm32 >> 16)));
466 } else {
467 try emit.writeInstruction(Instruction.mov(cond, scratch, Instruction.Operand.imm(@truncate(u8, imm32), 0)));
468 try emit.writeInstruction(Instruction.orr(cond, scratch, scratch, Instruction.Operand.imm(@truncate(u8, imm32 >> 8), 12)));
469 try emit.writeInstruction(Instruction.orr(cond, scratch, scratch, Instruction.Operand.imm(@truncate(u8, imm32 >> 16), 8)));
470 try emit.writeInstruction(Instruction.orr(cond, scratch, scratch, Instruction.Operand.imm(@truncate(u8, imm32 >> 24), 4)));
471 }
472
473 break :blk Instruction.Operand.reg(scratch, Instruction.Operand.Shift.none);
474 };
475
476 try emit.writeInstruction(Instruction.sub(cond, .sp, .sp, operand));
477 },
478 else => unreachable,
479 }
480}
481
430482fn mirShift(emit: *Emit, inst: Mir.Inst.Index) !void {
431483 const tag = emit.mir.instructions.items(.tag)[inst];
432484 const cond = emit.mir.instructions.items(.cond)[inst];
src/arch/arm/Mir.zig+9
......@@ -111,6 +111,11 @@ pub const Inst = struct {
111111 strh,
112112 /// Subtract
113113 sub,
114 /// Pseudo-instruction: Subtract 32-bit immediate from stack
115 ///
116 /// r0 can be used by Emit as a scratch register for loading
117 /// the immediate
118 sub_sp_scratch_r0,
114119 /// Subtract, update condition flags
115120 subs,
116121 /// Supervisor Call
......@@ -144,6 +149,10 @@ pub const Inst = struct {
144149 ///
145150 /// Used by e.g. svc
146151 imm24: u24,
152 /// A 32-bit immediate value.
153 ///
154 /// Used by e.g. sub_sp_scratch_r0
155 imm32: u32,
147156 /// Index into `extra`. Meaning of what can be found there is context-dependent.
148157 ///
149158 /// Used by e.g. load_memory
test/behavior/eval.zig-1
......@@ -1333,7 +1333,6 @@ test "lazy sizeof is resolved in division" {
13331333}
13341334
13351335test "lazy value is resolved as slice operand" {
1336 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13371336 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13381337
13391338 const A = struct { a: u32 };