aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2025-07-25 16:38:17 -0400
committerJacob Young <jacobly0@users.noreply.github.com>2025-07-26 16:08:40 -0400
commit1274254c48ee105623c513dfc01451fee2912c5b (patch)
tree612ff85297941fe4f7108ec62fd9ec28038d59a8 /src/codegen
parent7c349da49c73817139444570d3082ac1f0c93078 (diff)
downloadzig-1274254c48ee105623c513dfc01451fee2912c5b.tar.gz
zig-1274254c48ee105623c513dfc01451fee2912c5b.zip
aarch64: implement stack probing
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/aarch64/Select.zig73
-rw-r--r--src/codegen/aarch64/encoding.zig2
2 files changed, 51 insertions, 24 deletions
diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig
index 0a50cb6c9d..b0b1297a93 100644
--- a/src/codegen/aarch64/Select.zig
+++ b/src/codegen/aarch64/Select.zig
@@ -6693,8 +6693,8 @@ pub fn layout(
wip_mir_log.debug("{f}<body>:\n", .{nav.fqn.fmt(ip)});
const stack_size: u24 = @intCast(InternPool.Alignment.@"16".forward(isel.stack_size));
- const stack_size_low: u12 = @truncate(stack_size >> 0);
- const stack_size_high: u12 = @truncate(stack_size >> 12);
+ const stack_size_lo: u12 = @truncate(stack_size >> 0);
+ const stack_size_hi: u12 = @truncate(stack_size >> 12);
var saves_buf: [10 + 8 + 8 + 2 + 8]struct {
class: enum { integer, vector },
@@ -6881,28 +6881,53 @@ pub fn layout(
}
}
+ try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset }));
const scratch_reg: Register = if (isel.stack_align == .@"16")
.sp
- else if (stack_size == 0)
+ else if (stack_size == 0 and frame_record_offset == 0)
.fp
else
- .x9;
- try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset }));
- if (stack_size_high > 0) try isel.emit(.sub(scratch_reg, .sp, .{
- .shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },
- }));
- if (stack_size_low > 0) try isel.emit(.sub(
- scratch_reg,
- if (stack_size_high > 0) scratch_reg else .sp,
- .{ .immediate = stack_size_low },
- ));
- if (isel.stack_align != .@"16") {
- try isel.emit(.@"and"(.sp, scratch_reg, .{ .immediate = .{
- .N = .doubleword,
- .immr = -%isel.stack_align.toLog2Units(),
- .imms = ~isel.stack_align.toLog2Units(),
- } }));
+ .ip0;
+ if (mod.stack_check) {
+ if (stack_size_hi > 2) {
+ try isel.movImmediate(.ip1, stack_size_hi);
+ const loop_label = isel.instructions.items.len;
+ try isel.emit(.sub(.sp, .sp, .{
+ .shifted_immediate = .{ .immediate = 1, .lsl = .@"12" },
+ }));
+ try isel.emit(.sub(.ip1, .ip1, .{ .immediate = 1 }));
+ try isel.emit(.ldr(.xzr, .{ .base = .sp }));
+ try isel.emit(.cbnz(.ip1, -@as(i21, @intCast(
+ (isel.instructions.items.len - loop_label) << 2,
+ ))));
+ } else for (0..stack_size_hi) |_| {
+ try isel.emit(.sub(.sp, .sp, .{
+ .shifted_immediate = .{ .immediate = 1, .lsl = .@"12" },
+ }));
+ try isel.emit(.ldr(.xzr, .{ .base = .sp }));
+ }
+ if (stack_size_lo > 0) try isel.emit(.sub(
+ scratch_reg,
+ .sp,
+ .{ .immediate = stack_size_lo },
+ )) else if (scratch_reg.alias == Register.Alias.ip0)
+ try isel.emit(.add(scratch_reg, .sp, .{ .immediate = 0 }));
+ } else {
+ if (stack_size_hi > 0) try isel.emit(.sub(scratch_reg, .sp, .{
+ .shifted_immediate = .{ .immediate = stack_size_hi, .lsl = .@"12" },
+ }));
+ if (stack_size_lo > 0) try isel.emit(.sub(
+ scratch_reg,
+ if (stack_size_hi > 0) scratch_reg else .sp,
+ .{ .immediate = stack_size_lo },
+ )) else if (scratch_reg.alias == Register.Alias.ip0 and stack_size_hi == 0)
+ try isel.emit(.add(scratch_reg, .sp, .{ .immediate = 0 }));
}
+ if (isel.stack_align != .@"16") try isel.emit(.@"and"(.sp, scratch_reg, .{ .immediate = .{
+ .N = .doubleword,
+ .immr = -%isel.stack_align.toLog2Units(),
+ .imms = ~isel.stack_align.toLog2Units(),
+ } }));
wip_mir_log.debug("", .{});
}
@@ -6947,17 +6972,17 @@ pub fn layout(
save_index += 1;
} else save_index += 1;
}
- if (isel.stack_align != .@"16" or (stack_size_low > 0 and stack_size_high > 0)) {
+ if (isel.stack_align != .@"16" or (stack_size_lo > 0 and stack_size_hi > 0)) {
try isel.emit(switch (frame_record_offset) {
0 => .add(.sp, .fp, .{ .immediate = 0 }),
else => |offset| .sub(.sp, .fp, .{ .immediate = offset }),
});
} else {
- if (stack_size_high > 0) try isel.emit(.add(.sp, .sp, .{
- .shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },
+ if (stack_size_hi > 0) try isel.emit(.add(.sp, .sp, .{
+ .shifted_immediate = .{ .immediate = stack_size_hi, .lsl = .@"12" },
}));
- if (stack_size_low > 0) try isel.emit(.add(.sp, .sp, .{
- .immediate = stack_size_low,
+ if (stack_size_lo > 0) try isel.emit(.add(.sp, .sp, .{
+ .immediate = stack_size_lo,
}));
}
wip_mir_log.debug("{f}<epilogue>:\n", .{nav.fqn.fmt(ip)});
diff --git a/src/codegen/aarch64/encoding.zig b/src/codegen/aarch64/encoding.zig
index 1697b2957b..727b88c729 100644
--- a/src/codegen/aarch64/encoding.zig
+++ b/src/codegen/aarch64/encoding.zig
@@ -151,6 +151,7 @@ pub const Register = struct {
pub const wzr: Register = .{ .alias = .zr, .format = .{ .integer = .word } };
pub const wsp: Register = .{ .alias = .sp, .format = .{ .integer = .word } };
+ pub const ip = x16;
pub const ip0 = x16;
pub const ip1 = x17;
pub const fp = x29;
@@ -774,6 +775,7 @@ pub const Register = struct {
ffr,
+ pub const ip: Alias = .r16;
pub const ip0: Alias = .r16;
pub const ip1: Alias = .r17;
pub const fp: Alias = .r29;