authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-07-25 16:38:17-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-07-26 16:08:40-04:00
log1274254c48ee105623c513dfc01451fee2912c5b
tree612ff85297941fe4f7108ec62fd9ec28038d59a8
parent7c349da49c73817139444570d3082ac1f0c93078

aarch64: implement stack probing


4 files changed, 59 insertions(+), 28 deletions(-)

src/Package/Module.zig+1-1
......@@ -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+49-24
......@@ -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+2
......@@ -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+7-3
......@@ -248,9 +248,13 @@ pub fn selfHostedBackendIsAsRobustAsLlvm(target: *const std.Target) bool {
248248 return false;
249249}
250250
251pub 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);
251pub 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
256260pub fn supportsStackProtector(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {