mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 14:25:16 +00:00
stage2 ARM: support larger function stacks
This is done by introducing a new Mir pseudo-instruction
This commit is contained in:
parent
3794f2c493
commit
a0a7d15142
@ -488,14 +488,10 @@ fn gen(self: *Self) !void {
|
||||
const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align);
|
||||
const stack_size = aligned_total_stack_end - self.saved_regs_stack_space;
|
||||
self.max_end_stack = stack_size;
|
||||
if (Instruction.Operand.fromU32(stack_size)) |op| {
|
||||
self.mir_instructions.set(sub_reloc, .{
|
||||
.tag = .sub,
|
||||
.data = .{ .rr_op = .{ .rd = .sp, .rn = .sp, .op = op } },
|
||||
});
|
||||
} else {
|
||||
return self.failSymbol("TODO ARM: allow larger stacks", .{});
|
||||
}
|
||||
self.mir_instructions.set(sub_reloc, .{
|
||||
.tag = .sub_sp_scratch_r0,
|
||||
.data = .{ .imm32 = stack_size },
|
||||
});
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = .dbg_epilogue_begin,
|
||||
|
||||
@ -11,6 +11,7 @@ const link = @import("../../link.zig");
|
||||
const Module = @import("../../Module.zig");
|
||||
const Type = @import("../../type.zig").Type;
|
||||
const ErrorMsg = Module.ErrorMsg;
|
||||
const Target = std.Target;
|
||||
const assert = std.debug.assert;
|
||||
const DW = std.dwarf;
|
||||
const leb128 = std.leb;
|
||||
@ -93,6 +94,8 @@ pub fn emitMir(
|
||||
.sub => try emit.mirDataProcessing(inst),
|
||||
.subs => try emit.mirDataProcessing(inst),
|
||||
|
||||
.sub_sp_scratch_r0 => try emit.mirSubStackPointer(inst),
|
||||
|
||||
.asr => try emit.mirShift(inst),
|
||||
.lsl => try emit.mirShift(inst),
|
||||
.lsr => try emit.mirShift(inst),
|
||||
@ -190,6 +193,24 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {
|
||||
.dbg_epilogue_begin,
|
||||
.dbg_prologue_end,
|
||||
=> return 0,
|
||||
|
||||
.sub_sp_scratch_r0 => {
|
||||
const imm32 = emit.mir.instructions.items(.data)[inst].imm32;
|
||||
|
||||
if (imm32 == 0) {
|
||||
return 0 * 4;
|
||||
} else if (Instruction.Operand.fromU32(imm32) != null) {
|
||||
// sub
|
||||
return 1 * 4;
|
||||
} else if (Target.arm.featureSetHas(emit.target.cpu.features, .has_v7)) {
|
||||
// movw; movt; sub
|
||||
return 3 * 4;
|
||||
} else {
|
||||
// mov; orr; orr; orr; sub
|
||||
return 5 * 4;
|
||||
}
|
||||
},
|
||||
|
||||
else => return 4,
|
||||
}
|
||||
}
|
||||
@ -427,6 +448,37 @@ fn mirDataProcessing(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn mirSubStackPointer(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
const tag = emit.mir.instructions.items(.tag)[inst];
|
||||
const cond = emit.mir.instructions.items(.cond)[inst];
|
||||
const imm32 = emit.mir.instructions.items(.data)[inst].imm32;
|
||||
|
||||
switch (tag) {
|
||||
.sub_sp_scratch_r0 => {
|
||||
if (imm32 == 0) return;
|
||||
|
||||
const operand = Instruction.Operand.fromU32(imm32) orelse blk: {
|
||||
const scratch: Register = .r0;
|
||||
|
||||
if (Target.arm.featureSetHas(emit.target.cpu.features, .has_v7)) {
|
||||
try emit.writeInstruction(Instruction.movw(cond, scratch, @truncate(u16, imm32)));
|
||||
try emit.writeInstruction(Instruction.movt(cond, scratch, @truncate(u16, imm32 >> 16)));
|
||||
} else {
|
||||
try emit.writeInstruction(Instruction.mov(cond, scratch, Instruction.Operand.imm(@truncate(u8, imm32), 0)));
|
||||
try emit.writeInstruction(Instruction.orr(cond, scratch, scratch, Instruction.Operand.imm(@truncate(u8, imm32 >> 8), 12)));
|
||||
try emit.writeInstruction(Instruction.orr(cond, scratch, scratch, Instruction.Operand.imm(@truncate(u8, imm32 >> 16), 8)));
|
||||
try emit.writeInstruction(Instruction.orr(cond, scratch, scratch, Instruction.Operand.imm(@truncate(u8, imm32 >> 24), 4)));
|
||||
}
|
||||
|
||||
break :blk Instruction.Operand.reg(scratch, Instruction.Operand.Shift.none);
|
||||
};
|
||||
|
||||
try emit.writeInstruction(Instruction.sub(cond, .sp, .sp, operand));
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
fn mirShift(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
const tag = emit.mir.instructions.items(.tag)[inst];
|
||||
const cond = emit.mir.instructions.items(.cond)[inst];
|
||||
|
||||
@ -111,6 +111,11 @@ pub const Inst = struct {
|
||||
strh,
|
||||
/// Subtract
|
||||
sub,
|
||||
/// Pseudo-instruction: Subtract 32-bit immediate from stack
|
||||
///
|
||||
/// r0 can be used by Emit as a scratch register for loading
|
||||
/// the immediate
|
||||
sub_sp_scratch_r0,
|
||||
/// Subtract, update condition flags
|
||||
subs,
|
||||
/// Supervisor Call
|
||||
@ -144,6 +149,10 @@ pub const Inst = struct {
|
||||
///
|
||||
/// Used by e.g. svc
|
||||
imm24: u24,
|
||||
/// A 32-bit immediate value.
|
||||
///
|
||||
/// Used by e.g. sub_sp_scratch_r0
|
||||
imm32: u32,
|
||||
/// Index into `extra`. Meaning of what can be found there is context-dependent.
|
||||
///
|
||||
/// Used by e.g. load_memory
|
||||
|
||||
@ -1333,7 +1333,6 @@ test "lazy sizeof is resolved in division" {
|
||||
}
|
||||
|
||||
test "lazy value is resolved as slice operand" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
|
||||
const A = struct { a: u32 };
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user