| ... | @@ -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)}); |
| 6694 | | 6694 | |
| 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); |
| 6698 | | 6698 | |
| 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 | } |
| 6883 | | 6883 | |
| | 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 | .sp | 6886 | .sp |
| 6886 | else if (stack_size == 0) | 6887 | else if (stack_size == 0 and frame_record_offset == 0) |
| 6887 | .fp | 6888 | .fp |
| 6888 | else | 6889 | 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 | } |
| 6908 | | 6933 | |
| ... | @@ -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)}); |