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 {...@@ -250,7 +250,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
250 };250 };
251251
252 const stack_check = b: {252 const stack_check = b: {
253 if (!target_util.supportsStackProbing(target)) {253 if (!target_util.supportsStackProbing(target, zig_backend)) {
254 if (options.inherited.stack_check == true)254 if (options.inherited.stack_check == true)
255 return error.StackCheckUnsupportedByTarget;255 return error.StackCheckUnsupportedByTarget;
256 break :b false;256 break :b false;
src/codegen/aarch64/Select.zig+49-24
...@@ -6693,8 +6693,8 @@ pub fn layout(...@@ -6693,8 +6693,8 @@ pub fn layout(
6693 wip_mir_log.debug("{f}<body>:\n", .{nav.fqn.fmt(ip)});6693 wip_mir_log.debug("{f}<body>:\n", .{nav.fqn.fmt(ip)});
66946694
6695 const stack_size: u24 = @intCast(InternPool.Alignment.@"16".forward(isel.stack_size));6695 const stack_size: u24 = @intCast(InternPool.Alignment.@"16".forward(isel.stack_size));
6696 const stack_size_low: u12 = @truncate(stack_size >> 0);6696 const stack_size_lo: u12 = @truncate(stack_size >> 0);
6697 const stack_size_high: u12 = @truncate(stack_size >> 12);6697 const stack_size_hi: u12 = @truncate(stack_size >> 12);
66986698
6699 var saves_buf: [10 + 8 + 8 + 2 + 8]struct {6699 var saves_buf: [10 + 8 + 8 + 2 + 8]struct {
6700 class: enum { integer, vector },6700 class: enum { integer, vector },
...@@ -6881,28 +6881,53 @@ pub fn layout(...@@ -6881,28 +6881,53 @@ pub fn layout(
6881 }6881 }
6882 }6882 }
68836883
6884 try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset }));
6884 const scratch_reg: Register = if (isel.stack_align == .@"16")6885 const scratch_reg: Register = if (isel.stack_align == .@"16")
6885 .sp6886 .sp
6886 else if (stack_size == 0)6887 else if (stack_size == 0 and frame_record_offset == 0)
6887 .fp6888 .fp
6888 else6889 else
6889 .x9;6890 .ip0;
6890 try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset }));6891 if (mod.stack_check) {
6891 if (stack_size_high > 0) try isel.emit(.sub(scratch_reg, .sp, .{6892 if (stack_size_hi > 2) {
6892 .shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },6893 try isel.movImmediate(.ip1, stack_size_hi);
6893 }));6894 const loop_label = isel.instructions.items.len;
6894 if (stack_size_low > 0) try isel.emit(.sub(6895 try isel.emit(.sub(.sp, .sp, .{
6895 scratch_reg,6896 .shifted_immediate = .{ .immediate = 1, .lsl = .@"12" },
6896 if (stack_size_high > 0) scratch_reg else .sp,6897 }));
6897 .{ .immediate = stack_size_low },6898 try isel.emit(.sub(.ip1, .ip1, .{ .immediate = 1 }));
6898 ));6899 try isel.emit(.ldr(.xzr, .{ .base = .sp }));
6899 if (isel.stack_align != .@"16") {6900 try isel.emit(.cbnz(.ip1, -@as(i21, @intCast(
6900 try isel.emit(.@"and"(.sp, scratch_reg, .{ .immediate = .{6901 (isel.instructions.items.len - loop_label) << 2,
6901 .N = .doubleword,6902 ))));
6902 .immr = -%isel.stack_align.toLog2Units(),6903 } else for (0..stack_size_hi) |_| {
6903 .imms = ~isel.stack_align.toLog2Units(),6904 try isel.emit(.sub(.sp, .sp, .{
6904 } }));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 }));
6905 }6925 }
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 } }));
6906 wip_mir_log.debug("", .{});6931 wip_mir_log.debug("", .{});
6907 }6932 }
69086933
...@@ -6947,17 +6972,17 @@ pub fn layout(...@@ -6947,17 +6972,17 @@ pub fn layout(
6947 save_index += 1;6972 save_index += 1;
6948 } else save_index += 1;6973 } else save_index += 1;
6949 }6974 }
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)) {
6951 try isel.emit(switch (frame_record_offset) {6976 try isel.emit(switch (frame_record_offset) {
6952 0 => .add(.sp, .fp, .{ .immediate = 0 }),6977 0 => .add(.sp, .fp, .{ .immediate = 0 }),
6953 else => |offset| .sub(.sp, .fp, .{ .immediate = offset }),6978 else => |offset| .sub(.sp, .fp, .{ .immediate = offset }),
6954 });6979 });
6955 } else {6980 } else {
6956 if (stack_size_high > 0) try isel.emit(.add(.sp, .sp, .{6981 if (stack_size_hi > 0) try isel.emit(.add(.sp, .sp, .{
6957 .shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },6982 .shifted_immediate = .{ .immediate = stack_size_hi, .lsl = .@"12" },
6958 }));6983 }));
6959 if (stack_size_low > 0) try isel.emit(.add(.sp, .sp, .{6984 if (stack_size_lo > 0) try isel.emit(.add(.sp, .sp, .{
6960 .immediate = stack_size_low,6985 .immediate = stack_size_lo,
6961 }));6986 }));
6962 }6987 }
6963 wip_mir_log.debug("{f}<epilogue>:\n", .{nav.fqn.fmt(ip)});6988 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 {...@@ -151,6 +151,7 @@ pub const Register = struct {
151 pub const wzr: Register = .{ .alias = .zr, .format = .{ .integer = .word } };151 pub const wzr: Register = .{ .alias = .zr, .format = .{ .integer = .word } };
152 pub const wsp: Register = .{ .alias = .sp, .format = .{ .integer = .word } };152 pub const wsp: Register = .{ .alias = .sp, .format = .{ .integer = .word } };
153153
154 pub const ip = x16;
154 pub const ip0 = x16;155 pub const ip0 = x16;
155 pub const ip1 = x17;156 pub const ip1 = x17;
156 pub const fp = x29;157 pub const fp = x29;
...@@ -774,6 +775,7 @@ pub const Register = struct {...@@ -774,6 +775,7 @@ pub const Register = struct {
774775
775 ffr,776 ffr,
776777
778 pub const ip: Alias = .r16;
777 pub const ip0: Alias = .r16;779 pub const ip0: Alias = .r16;
778 pub const ip1: Alias = .r17;780 pub const ip1: Alias = .r17;
779 pub const fp: Alias = .r29;781 pub const fp: Alias = .r29;
src/target.zig+7-3
...@@ -248,9 +248,13 @@ pub fn selfHostedBackendIsAsRobustAsLlvm(target: *const std.Target) bool {...@@ -248,9 +248,13 @@ pub fn selfHostedBackendIsAsRobustAsLlvm(target: *const std.Target) bool {
248 return false;248 return false;
249}249}
250250
251pub fn supportsStackProbing(target: *const std.Target) bool {251pub fn supportsStackProbing(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {
252 return target.os.tag != .windows and target.os.tag != .uefi and252 return switch (backend) {
253 (target.cpu.arch == .x86 or target.cpu.arch == .x86_64);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 };
254}258}
255259
256pub fn supportsStackProtector(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {260pub fn supportsStackProtector(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {