| ... | ... | @@ -6693,8 +6693,8 @@ pub fn layout( |
| 6693 | 6693 | wip_mir_log.debug("{f}<body>:\n", .{nav.fqn.fmt(ip)}); |
| 6694 | 6694 | |
| 6695 | 6695 | 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); |
| 6698 | 6698 | |
| 6699 | 6699 | var saves_buf: [10 + 8 + 8 + 2 + 8]struct { |
| 6700 | 6700 | class: enum { integer, vector }, |
| ... | ... | @@ -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 | 6885 | const scratch_reg: Register = if (isel.stack_align == .@"16") |
| 6885 | 6886 | .sp |
| 6886 | | else if (stack_size == 0) |
| 6887 | else if (stack_size == 0 and frame_record_offset == 0) |
| 6887 | 6888 | .fp |
| 6888 | 6889 | 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 })); |
| 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 | 6931 | wip_mir_log.debug("", .{}); |
| 6907 | 6932 | } |
| 6908 | 6933 | |
| ... | ... | @@ -6947,17 +6972,17 @@ pub fn layout( |
| 6947 | 6972 | save_index += 1; |
| 6948 | 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 | 6976 | try isel.emit(switch (frame_record_offset) { |
| 6952 | 6977 | 0 => .add(.sp, .fp, .{ .immediate = 0 }), |
| 6953 | 6978 | else => |offset| .sub(.sp, .fp, .{ .immediate = offset }), |
| 6954 | 6979 | }); |
| 6955 | 6980 | } 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" }, |
| 6958 | 6983 | })); |
| 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, |
| 6961 | 6986 | })); |
| 6962 | 6987 | } |
| 6963 | 6988 | wip_mir_log.debug("{f}<epilogue>:\n", .{nav.fqn.fmt(ip)}); |