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
signaturelock-open 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 {...@@ -488,14 +488,10 @@ fn gen(self: *Self) !void {
488 const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align);488 const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align);
489 const stack_size = aligned_total_stack_end - self.saved_regs_stack_space;489 const stack_size = aligned_total_stack_end - self.saved_regs_stack_space;
490 self.max_end_stack = stack_size;490 self.max_end_stack = stack_size;
491 if (Instruction.Operand.fromU32(stack_size)) |op| {491 self.mir_instructions.set(sub_reloc, .{
492 self.mir_instructions.set(sub_reloc, .{492 .tag = .sub_sp_scratch_r0,
493 .tag = .sub,493 .data = .{ .imm32 = stack_size },
494 .data = .{ .rr_op = .{ .rd = .sp, .rn = .sp, .op = op } },494 });
495 });
496 } else {
497 return self.failSymbol("TODO ARM: allow larger stacks", .{});
498 }
499495
500 _ = try self.addInst(.{496 _ = try self.addInst(.{
501 .tag = .dbg_epilogue_begin,497 .tag = .dbg_epilogue_begin,
src/arch/arm/Emit.zig+52
...@@ -11,6 +11,7 @@ const link = @import("../../link.zig");...@@ -11,6 +11,7 @@ const link = @import("../../link.zig");
11const Module = @import("../../Module.zig");11const Module = @import("../../Module.zig");
12const Type = @import("../../type.zig").Type;12const Type = @import("../../type.zig").Type;
13const ErrorMsg = Module.ErrorMsg;13const ErrorMsg = Module.ErrorMsg;
14const Target = std.Target;
14const assert = std.debug.assert;15const assert = std.debug.assert;
15const DW = std.dwarf;16const DW = std.dwarf;
16const leb128 = std.leb;17const leb128 = std.leb;
...@@ -93,6 +94,8 @@ pub fn emitMir(...@@ -93,6 +94,8 @@ pub fn emitMir(
93 .sub => try emit.mirDataProcessing(inst),94 .sub => try emit.mirDataProcessing(inst),
94 .subs => try emit.mirDataProcessing(inst),95 .subs => try emit.mirDataProcessing(inst),
9596
97 .sub_sp_scratch_r0 => try emit.mirSubStackPointer(inst),
98
96 .asr => try emit.mirShift(inst),99 .asr => try emit.mirShift(inst),
97 .lsl => try emit.mirShift(inst),100 .lsl => try emit.mirShift(inst),
98 .lsr => try emit.mirShift(inst),101 .lsr => try emit.mirShift(inst),
...@@ -190,6 +193,24 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {...@@ -190,6 +193,24 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {
190 .dbg_epilogue_begin,193 .dbg_epilogue_begin,
191 .dbg_prologue_end,194 .dbg_prologue_end,
192 => return 0,195 => 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
193 else => return 4,214 else => return 4,
194 }215 }
195}216}
...@@ -427,6 +448,37 @@ fn mirDataProcessing(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -427,6 +448,37 @@ fn mirDataProcessing(emit: *Emit, inst: Mir.Inst.Index) !void {
427 }448 }
428}449}
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
430fn mirShift(emit: *Emit, inst: Mir.Inst.Index) !void {482fn mirShift(emit: *Emit, inst: Mir.Inst.Index) !void {
431 const tag = emit.mir.instructions.items(.tag)[inst];483 const tag = emit.mir.instructions.items(.tag)[inst];
432 const cond = emit.mir.instructions.items(.cond)[inst];484 const cond = emit.mir.instructions.items(.cond)[inst];
src/arch/arm/Mir.zig+9
...@@ -111,6 +111,11 @@ pub const Inst = struct {...@@ -111,6 +111,11 @@ pub const Inst = struct {
111 strh,111 strh,
112 /// Subtract112 /// Subtract
113 sub,113 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,
114 /// Subtract, update condition flags119 /// Subtract, update condition flags
115 subs,120 subs,
116 /// Supervisor Call121 /// Supervisor Call
...@@ -144,6 +149,10 @@ pub const Inst = struct {...@@ -144,6 +149,10 @@ pub const Inst = struct {
144 ///149 ///
145 /// Used by e.g. svc150 /// Used by e.g. svc
146 imm24: u24,151 imm24: u24,
152 /// A 32-bit immediate value.
153 ///
154 /// Used by e.g. sub_sp_scratch_r0
155 imm32: u32,
147 /// Index into `extra`. Meaning of what can be found there is context-dependent.156 /// Index into `extra`. Meaning of what can be found there is context-dependent.
148 ///157 ///
149 /// Used by e.g. load_memory158 /// Used by e.g. load_memory
test/behavior/eval.zig-1
...@@ -1333,7 +1333,6 @@ test "lazy sizeof is resolved in division" {...@@ -1333,7 +1333,6 @@ test "lazy sizeof is resolved in division" {
1333}1333}
13341334
1335test "lazy value is resolved as slice operand" {1335test "lazy value is resolved as slice operand" {
1336 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1337 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1336 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13381337
1339 const A = struct { a: u32 };1338 const A = struct { a: u32 };