Skip to content

Commit 1274254

Browse files
committed
aarch64: implement stack probing
1 parent 7c349da commit 1274254

File tree

4 files changed

+59
-28
lines changed

4 files changed

+59
-28
lines changed

src/Package/Module.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
250250
};
251251

252252
const stack_check = b: {
253-
if (!target_util.supportsStackProbing(target)) {
253+
if (!target_util.supportsStackProbing(target, zig_backend)) {
254254
if (options.inherited.stack_check == true)
255255
return error.StackCheckUnsupportedByTarget;
256256
break :b false;

src/codegen/aarch64/Select.zig

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6693,8 +6693,8 @@ pub fn layout(
66936693
wip_mir_log.debug("{f}<body>:\n", .{nav.fqn.fmt(ip)});
66946694

66956695
const stack_size: u24 = @intCast(InternPool.Alignment.@"16".forward(isel.stack_size));
6696-
const stack_size_low: u12 = @truncate(stack_size >> 0);
6697-
const stack_size_high: u12 = @truncate(stack_size >> 12);
6696+
const stack_size_lo: u12 = @truncate(stack_size >> 0);
6697+
const stack_size_hi: u12 = @truncate(stack_size >> 12);
66986698

66996699
var saves_buf: [10 + 8 + 8 + 2 + 8]struct {
67006700
class: enum { integer, vector },
@@ -6881,28 +6881,53 @@ pub fn layout(
68816881
}
68826882
}
68836883

6884+
try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset }));
68846885
const scratch_reg: Register = if (isel.stack_align == .@"16")
68856886
.sp
6886-
else if (stack_size == 0)
6887+
else if (stack_size == 0 and frame_record_offset == 0)
68876888
.fp
68886889
else
6889-
.x9;
6890-
try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset }));
6891-
if (stack_size_high > 0) try isel.emit(.sub(scratch_reg, .sp, .{
6892-
.shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },
6893-
}));
6894-
if (stack_size_low > 0) try isel.emit(.sub(
6895-
scratch_reg,
6896-
if (stack_size_high > 0) scratch_reg else .sp,
6897-
.{ .immediate = stack_size_low },
6898-
));
6899-
if (isel.stack_align != .@"16") {
6900-
try isel.emit(.@"and"(.sp, scratch_reg, .{ .immediate = .{
6901-
.N = .doubleword,
6902-
.immr = -%isel.stack_align.toLog2Units(),
6903-
.imms = ~isel.stack_align.toLog2Units(),
6904-
} }));
6890+
.ip0;
6891+
if (mod.stack_check) {
6892+
if (stack_size_hi > 2) {
6893+
try isel.movImmediate(.ip1, stack_size_hi);
6894+
const loop_label = isel.instructions.items.len;
6895+
try isel.emit(.sub(.sp, .sp, .{
6896+
.shifted_immediate = .{ .immediate = 1, .lsl = .@"12" },
6897+
}));
6898+
try isel.emit(.sub(.ip1, .ip1, .{ .immediate = 1 }));
6899+
try isel.emit(.ldr(.xzr, .{ .base = .sp }));
6900+
try isel.emit(.cbnz(.ip1, -@as(i21, @intCast(
6901+
(isel.instructions.items.len - loop_label) << 2,
6902+
))));
6903+
} else for (0..stack_size_hi) |_| {
6904+
try isel.emit(.sub(.sp, .sp, .{
6905+
.shifted_immediate = .{ .immediate = 1, .lsl = .@"12" },
6906+
}));
6907+
try isel.emit(.ldr(.xzr, .{ .base = .sp }));
6908+
}
6909+
if (stack_size_lo > 0) try isel.emit(.sub(
6910+
scratch_reg,
6911+
.sp,
6912+
.{ .immediate = stack_size_lo },
6913+
)) else if (scratch_reg.alias == Register.Alias.ip0)
6914+
try isel.emit(.add(scratch_reg, .sp, .{ .immediate = 0 }));
6915+
} else {
6916+
if (stack_size_hi > 0) try isel.emit(.sub(scratch_reg, .sp, .{
6917+
.shifted_immediate = .{ .immediate = stack_size_hi, .lsl = .@"12" },
6918+
}));
6919+
if (stack_size_lo > 0) try isel.emit(.sub(
6920+
scratch_reg,
6921+
if (stack_size_hi > 0) scratch_reg else .sp,
6922+
.{ .immediate = stack_size_lo },
6923+
)) else if (scratch_reg.alias == Register.Alias.ip0 and stack_size_hi == 0)
6924+
try isel.emit(.add(scratch_reg, .sp, .{ .immediate = 0 }));
69056925
}
6926+
if (isel.stack_align != .@"16") try isel.emit(.@"and"(.sp, scratch_reg, .{ .immediate = .{
6927+
.N = .doubleword,
6928+
.immr = -%isel.stack_align.toLog2Units(),
6929+
.imms = ~isel.stack_align.toLog2Units(),
6930+
} }));
69066931
wip_mir_log.debug("", .{});
69076932
}
69086933

@@ -6947,17 +6972,17 @@ pub fn layout(
69476972
save_index += 1;
69486973
} else save_index += 1;
69496974
}
6950-
if (isel.stack_align != .@"16" or (stack_size_low > 0 and stack_size_high > 0)) {
6975+
if (isel.stack_align != .@"16" or (stack_size_lo > 0 and stack_size_hi > 0)) {
69516976
try isel.emit(switch (frame_record_offset) {
69526977
0 => .add(.sp, .fp, .{ .immediate = 0 }),
69536978
else => |offset| .sub(.sp, .fp, .{ .immediate = offset }),
69546979
});
69556980
} else {
6956-
if (stack_size_high > 0) try isel.emit(.add(.sp, .sp, .{
6957-
.shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },
6981+
if (stack_size_hi > 0) try isel.emit(.add(.sp, .sp, .{
6982+
.shifted_immediate = .{ .immediate = stack_size_hi, .lsl = .@"12" },
69586983
}));
6959-
if (stack_size_low > 0) try isel.emit(.add(.sp, .sp, .{
6960-
.immediate = stack_size_low,
6984+
if (stack_size_lo > 0) try isel.emit(.add(.sp, .sp, .{
6985+
.immediate = stack_size_lo,
69616986
}));
69626987
}
69636988
wip_mir_log.debug("{f}<epilogue>:\n", .{nav.fqn.fmt(ip)});

src/codegen/aarch64/encoding.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ pub const Register = struct {
151151
pub const wzr: Register = .{ .alias = .zr, .format = .{ .integer = .word } };
152152
pub const wsp: Register = .{ .alias = .sp, .format = .{ .integer = .word } };
153153

154+
pub const ip = x16;
154155
pub const ip0 = x16;
155156
pub const ip1 = x17;
156157
pub const fp = x29;
@@ -774,6 +775,7 @@ pub const Register = struct {
774775

775776
ffr,
776777

778+
pub const ip: Alias = .r16;
777779
pub const ip0: Alias = .r16;
778780
pub const ip1: Alias = .r17;
779781
pub const fp: Alias = .r29;

src/target.zig

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,13 @@ pub fn selfHostedBackendIsAsRobustAsLlvm(target: *const std.Target) bool {
248248
return false;
249249
}
250250

251-
pub fn supportsStackProbing(target: *const std.Target) bool {
252-
return target.os.tag != .windows and target.os.tag != .uefi and
253-
(target.cpu.arch == .x86 or target.cpu.arch == .x86_64);
251+
pub fn supportsStackProbing(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {
252+
return switch (backend) {
253+
.stage2_aarch64, .stage2_x86_64 => true,
254+
.stage2_llvm => target.os.tag != .windows and target.os.tag != .uefi and
255+
(target.cpu.arch == .x86 or target.cpu.arch == .x86_64),
256+
else => false,
257+
};
254258
}
255259

256260
pub fn supportsStackProtector(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {

0 commit comments

Comments
 (0)