diff options
| -rw-r--r-- | library/alloc/src/lib.rs | 1 | ||||
| -rw-r--r-- | library/core/src/lib.rs | 2 | ||||
| -rw-r--r-- | library/core/src/pin.rs | 20 | ||||
| -rw-r--r-- | library/core/tests/lib.rs | 2 | ||||
| -rw-r--r-- | library/core/tests/pin.rs | 4 | ||||
| -rw-r--r-- | tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs | 47 | ||||
| -rw-r--r-- | tests/run-make/avr-rjmp-offset/rmake.rs | 60 |
7 files changed, 123 insertions, 13 deletions
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 0a4a5160d82..ae9b3739858 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -112,7 +112,6 @@ #![feature(const_eval_select)] #![feature(const_heap)] #![feature(const_maybe_uninit_write)] -#![feature(const_pin)] #![feature(const_size_of_val)] #![feature(const_vec_string_slice)] #![feature(core_intrinsics)] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 6ed9ccaa694..ad034d3e576 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -129,7 +129,7 @@ #![feature(const_nonnull_new)] #![feature(const_num_midpoint)] #![feature(const_option_ext)] -#![feature(const_pin)] +#![feature(const_pin_2)] #![feature(const_pointer_is_aligned)] #![feature(const_ptr_is_null)] #![feature(const_ptr_sub_ptr)] diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index fac789dbd99..5d5733d38fc 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1186,7 +1186,7 @@ impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> { /// let mut pinned: Pin<&mut u8> = Pin::new(&mut val); /// ``` #[inline(always)] - #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] #[stable(feature = "pin", since = "1.33.0")] pub const fn new(pointer: Ptr) -> Pin<Ptr> { // SAFETY: the value pointed to is `Unpin`, and so has no requirements @@ -1214,7 +1214,7 @@ impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> { /// assert_eq!(*r, 5); /// ``` #[inline(always)] - #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + #[rustc_const_unstable(feature = "const_pin_2", issue = "76654")] #[stable(feature = "pin_into_inner", since = "1.39.0")] pub const fn into_inner(pin: Pin<Ptr>) -> Ptr { pin.__pointer @@ -1351,7 +1351,7 @@ impl<Ptr: Deref> Pin<Ptr> { /// [`pin` module docs]: self #[lang = "new_unchecked"] #[inline(always)] - #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] #[stable(feature = "pin", since = "1.33.0")] pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin<Ptr> { Pin { __pointer: pointer } @@ -1503,7 +1503,7 @@ impl<Ptr: Deref> Pin<Ptr> { /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used /// instead. #[inline(always)] - #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + #[rustc_const_unstable(feature = "const_pin_2", issue = "76654")] #[stable(feature = "pin_into_inner", since = "1.39.0")] pub const unsafe fn into_inner_unchecked(pin: Pin<Ptr>) -> Ptr { pin.__pointer @@ -1559,7 +1559,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// ["pinning projections"]: self#projections-and-structural-pinning #[inline(always)] #[must_use] - #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] #[stable(feature = "pin", since = "1.33.0")] pub const fn get_ref(self) -> &'a T { self.__pointer @@ -1570,7 +1570,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime. #[inline(always)] #[must_use = "`self` will be dropped if the result is not used"] - #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] #[stable(feature = "pin", since = "1.33.0")] pub const fn into_ref(self) -> Pin<&'a T> { Pin { __pointer: self.__pointer } @@ -1588,7 +1588,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { #[inline(always)] #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "pin", since = "1.33.0")] - #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] pub const fn get_mut(self) -> &'a mut T where T: Unpin, @@ -1609,7 +1609,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { #[inline(always)] #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "pin", since = "1.33.0")] - #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn get_unchecked_mut(self) -> &'a mut T { self.__pointer } @@ -1652,7 +1652,7 @@ impl<T: ?Sized> Pin<&'static T> { /// This is safe because `T` is borrowed immutably for the `'static` lifetime, which /// never ends. #[stable(feature = "pin_static_ref", since = "1.61.0")] - #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] pub const fn static_ref(r: &'static T) -> Pin<&'static T> { // SAFETY: The 'static borrow guarantees the data will not be // moved/invalidated until it gets dropped (which is never). @@ -1666,7 +1666,7 @@ impl<T: ?Sized> Pin<&'static mut T> { /// This is safe because `T` is borrowed for the `'static` lifetime, which /// never ends. #[stable(feature = "pin_static_ref", since = "1.61.0")] - #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] pub const fn static_mut(r: &'static mut T) -> Pin<&'static mut T> { // SAFETY: The 'static borrow guarantees the data will not be // moved/invalidated until it gets dropped (which is never). diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index bfc0b638b7e..443090097c0 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -21,7 +21,7 @@ #![feature(const_likely)] #![feature(const_nonnull_new)] #![feature(const_option_ext)] -#![feature(const_pin)] +#![feature(const_pin_2)] #![feature(const_pointer_is_aligned)] #![feature(const_three_way_compare)] #![feature(const_trait_impl)] diff --git a/library/core/tests/pin.rs b/library/core/tests/pin.rs index 7a6af46a743..026d2ca8de2 100644 --- a/library/core/tests/pin.rs +++ b/library/core/tests/pin.rs @@ -19,6 +19,10 @@ fn pin_const() { const REF: &'static usize = PINNED.get_ref(); assert_eq!(REF, POINTER); + const INT: u8 = 42; + const STATIC_REF: Pin<&'static u8> = Pin::static_ref(&INT); + assert_eq!(*STATIC_REF, INT); + // Note: `pin_mut_const` tests that the methods of `Pin<&mut T>` are usable in a const context. // A const fn is used because `&mut` is not (yet) usable in constants. const fn pin_mut_const() { diff --git a/tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs b/tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs new file mode 100644 index 00000000000..2f97fc1ed95 --- /dev/null +++ b/tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs @@ -0,0 +1,47 @@ +//! This test case is a `#![no_core]`-version of the MVCE presented in #129301. +//! +//! The function [`delay()`] is removed, as it is not necessary to trigger the +//! wrong behavior and would require some additional lang items. +#![feature(no_core, lang_items, intrinsics, rustc_attrs)] +#![no_core] +#![no_main] +#![allow(internal_features)] + +use minicore::ptr; + +#[no_mangle] +pub fn main() -> ! { + let port_b = 0x25 as *mut u8; // the I/O-address of PORTB + + // a simple loop with some trivial instructions within. This loop label has + // to be placed correctly before the `ptr::write_volatile()` (some LLVM ver- + // sions did place it after the first loop instruction, causing unsoundness) + loop { + unsafe { ptr::write_volatile(port_b, 1) }; + unsafe { ptr::write_volatile(port_b, 2) }; + } +} + +// FIXME: replace with proper minicore once available (#130693) +mod minicore { + #[lang = "sized"] + pub trait Sized {} + + #[lang = "copy"] + pub trait Copy {} + impl Copy for u32 {} + impl Copy for &u32 {} + impl<T: ?Sized> Copy for *mut T {} + + pub mod ptr { + #[inline] + #[rustc_diagnostic_item = "ptr_write_volatile"] + pub unsafe fn write_volatile<T>(dst: *mut T, src: T) { + extern "rust-intrinsic" { + #[rustc_nounwind] + pub fn volatile_store<T>(dst: *mut T, val: T); + } + unsafe { volatile_store(dst, src) }; + } + } +} diff --git a/tests/run-make/avr-rjmp-offset/rmake.rs b/tests/run-make/avr-rjmp-offset/rmake.rs new file mode 100644 index 00000000000..89cbca309be --- /dev/null +++ b/tests/run-make/avr-rjmp-offset/rmake.rs @@ -0,0 +1,60 @@ +//@ needs-llvm-components: avr +//@ needs-rust-lld +//! Regression test for #129301/llvm-project#106722 within `rustc`. +//! +//! Some LLVM-versions had wrong offsets in the local labels, causing the first +//! loop instruction to be missed. This test therefore contains a simple loop +//! with trivial instructions in it, to see, where the label is placed. +//! +//! This must be a `rmake`-test and cannot be a `tests/assembly`-test, since the +//! wrong output is only produced with direct assembly generation, but not when +//! "emit-asm" is used, as described in the issue description of #129301: +//! https://github.com/rust-lang/rust/issues/129301#issue-2475070770 +use run_make_support::{llvm_objdump, rustc}; + +fn main() { + rustc() + .input("avr-rjmp-offsets.rs") + .opt_level("s") + .panic("abort") + .target("avr-unknown-gnu-atmega328") + // normally one links with `avr-gcc`, but this is not available in CI, + // hence this test diverges from the default behavior to enable linking + // at all, which is necessary for the test (to resolve the labels). To + // not depend on a special linker script, the main-function is marked as + // the entry function, causing the linker to not remove it. + .linker("rust-lld") + .link_arg("--entry=main") + .output("compiled") + .run(); + + let disassembly = llvm_objdump().disassemble().input("compiled").run().stdout_utf8(); + + // search for the following instruction sequence: + // ```disassembly + // 00000080 <main>: + // 80: 81 e0 ldi r24, 0x1 + // 82: 92 e0 ldi r25, 0x2 + // 84: 85 b9 out 0x5, r24 + // 86: 95 b9 out 0x5, r25 + // 88: fd cf rjmp .-6 + // ``` + // This matches on all instructions, since the size of the instructions be- + // fore the relative jump has an impact on the label offset. Old versions + // of the Rust compiler did produce a label `rjmp .-4` (misses the first + // instruction in the loop). + assert!(disassembly.contains("<main>"), "no main function in output"); + disassembly + .trim() + .lines() + .skip_while(|&line| !line.contains("<main>")) + .inspect(|line| println!("{line}")) + .skip(1) + .zip(["ldi\t", "ldi\t", "out\t", "out\t", "rjmp\t.-6"]) + .for_each(|(line, expected_instruction)| { + assert!( + line.contains(expected_instruction), + "expected instruction `{expected_instruction}`, got `{line}`" + ); + }); +} |
