From 7b731ca15a43bd88049fe0e5dbef73e88a576a19 Mon Sep 17 00:00:00 2001
From: Jubilee Young <workingjubilee@gmail.com>
Date: Wed, 2 Oct 2024 00:58:56 -0700
Subject: [PATCH] compiler: dont try to compile impossible alignment on 16-bit

---
 compiler/rustc_ty_utils/src/layout.rs         |  8 ++++
 .../repr/16-bit-align-too-big.msp430.stderr   |  4 ++
 tests/ui/repr/16-bit-align-too-big.rs         | 38 +++++++++++++++++++
 3 files changed, 50 insertions(+)
 create mode 100644 tests/ui/repr/16-bit-align-too-big.msp430.stderr
 create mode 100644 tests/ui/repr/16-bit-align-too-big.rs

diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 34c9f1b63c066..25e3c0b9ffff6 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -6,6 +6,7 @@ use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::bug;
+use rustc_middle::mir::interpret::PointerArithmetic;
 use rustc_middle::mir::{CoroutineLayout, CoroutineSavedLocal};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{
@@ -562,6 +563,13 @@ fn layout_of_uncached<'tcx>(
                 ));
             }
 
+            // we're on a 16-bit target and this alignment is too big
+            if let Some(align) = def.repr().align {
+                if align.bytes() > (cx.target_isize_max() as u64) {
+                    return Err(error(cx, LayoutError::SizeOverflow(ty)));
+                }
+            }
+
             let get_discriminant_type =
                 |min, max| Integer::repr_discr(tcx, ty, &def.repr(), min, max);
 
diff --git a/tests/ui/repr/16-bit-align-too-big.msp430.stderr b/tests/ui/repr/16-bit-align-too-big.msp430.stderr
new file mode 100644
index 0000000000000..2deaee1b287a7
--- /dev/null
+++ b/tests/ui/repr/16-bit-align-too-big.msp430.stderr
@@ -0,0 +1,4 @@
+error: values of the type `Hello16BitAlign` are too big for the target architecture
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/repr/16-bit-align-too-big.rs b/tests/ui/repr/16-bit-align-too-big.rs
new file mode 100644
index 0000000000000..49768c14d42bd
--- /dev/null
+++ b/tests/ui/repr/16-bit-align-too-big.rs
@@ -0,0 +1,38 @@
+// We should fail to compute alignment for types aligned higher than usize::MAX.
+// We can't handle alignments that require all 32 bits, so this only affects 16-bit.
+
+//@ revisions: msp430 aarch32
+//@ [msp430] build-fail
+//@ [msp430] needs-llvm-components: msp430
+//@ [msp430] compile-flags: --target=msp430-none-elf
+//@ [msp430] error-pattern: values of the type `Hello16BitAlign` are too big for the target architecture
+
+//@ [aarch32] build-pass
+//@ [aarch32] needs-llvm-components: arm
+//@ [aarch32] compile-flags: --target=thumbv7m-none-eabi
+
+#![feature(no_core, lang_items, intrinsics, staged_api, rustc_attrs)]
+#![no_core]
+#![crate_type = "lib"]
+#![stable(feature = "intrinsics_for_test", since = "3.3.3")]
+#![allow(dead_code)]
+
+extern "rust-intrinsic" {
+    #[stable(feature = "intrinsics_for_test", since = "3.3.3")]
+    #[rustc_const_stable(feature = "intrinsics_for_test", since = "3.3.3")]
+    #[rustc_safe_intrinsic]
+    fn min_align_of<T>() -> usize;
+}
+
+#[lang="sized"]
+trait Sized {}
+#[lang="copy"]
+trait Copy {}
+
+#[repr(align(65536))]
+#[stable(feature = "intrinsics_for_test", since = "3.3.3")]
+pub struct Hello16BitAlign;
+
+
+#[stable(feature = "intrinsics_for_test", since = "3.3.3")]
+pub fn bar() -> usize { min_align_of::<Hello16BitAlign>() }