Skip to content

Commit 5a4e266

Browse files
committed
Auto merge of #155506 - jhpratt:rollup-tMDKAQS, r=jhpratt
Rollup of 9 pull requests Successful merges: - #155370 (Add regression test for dead code elimination with drop + panic) - #154823 (Replace the spdx-rs dependency with a minimal in-tree SPDX tag-value parser) - #154972 (Implement `core::arch::return_address` and tests) - #155294 (Add test for coalescing of diagnostic attribute duplicates) - #155352 (triagebot.toml: Sync `assign.owners` with `autolabel."T-compiler"`) - #155431 (Add temporary scope to assert_matches) - #152995 (ACP Implementation of PermissionsExt for Windows ) - #153873 (deprecate `std::char` constants and functions) - #154865 (libtest: use binary search for --exact test filtering)
2 parents ec2d669 + 4cb516d commit 5a4e266

31 files changed

Lines changed: 729 additions & 163 deletions

File tree

Cargo.lock

Lines changed: 41 additions & 108 deletions
Large diffs are not rendered by default.

compiler/rustc_builtin_macros/src/test_harness.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,8 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> Box<ast::Expr> {
370370
let ecx = &cx.ext_cx;
371371

372372
let mut tests = cx.test_cases.clone();
373+
// Note that this sort is load-bearing: the libtest harness uses binary search to find tests by
374+
// name.
373375
tests.sort_by(|a, b| a.name.as_str().cmp(b.name.as_str()));
374376

375377
ecx.expr_array_ref(

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,6 +1529,12 @@ fn codegen_regular_intrinsic_call<'tcx>(
15291529
fx.bcx.set_cold_block(fx.bcx.current_block().unwrap());
15301530
}
15311531

1532+
sym::return_address => {
1533+
let val = fx.bcx.ins().get_return_address(fx.pointer_type);
1534+
let val = CValue::by_val(val, ret.layout());
1535+
ret.write_cvalue(fx, val);
1536+
}
1537+
15321538
// Unimplemented intrinsics must have a fallback body. The fallback body is obtained
15331539
// by converting the `InstanceKind::Intrinsic` to an `InstanceKind::Item`.
15341540
_ => {

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,12 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
788788
}
789789
}
790790

791+
sym::return_address => {
792+
let ty = self.type_ix(32);
793+
let val = self.const_int(ty, 0);
794+
self.call_intrinsic("llvm.returnaddress", &[], &[val])
795+
}
796+
791797
_ => {
792798
debug!("unknown intrinsic '{}' -- falling back to default body", name);
793799
// Call the fallback body instead of generating the intrinsic code

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
120120
| sym::contract_checks
121121
| sym::atomic_fence
122122
| sym::atomic_singlethreadfence
123-
| sym::caller_location => {}
123+
| sym::caller_location
124+
| sym::return_address => {}
124125
_ => {
125126
span_bug!(
126127
span,

compiler/rustc_hir_analysis/src/check/intrinsic.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
179179
| sym::ptr_guaranteed_cmp
180180
| sym::ptr_mask
181181
| sym::ptr_metadata
182+
| sym::return_address
182183
| sym::rotate_left
183184
| sym::rotate_right
184185
| sym::round_ties_even_f16
@@ -801,6 +802,8 @@ pub(crate) fn check_intrinsic_type(
801802
| sym::atomic_xor => (2, 1, vec![Ty::new_mut_ptr(tcx, param(0)), param(1)], param(0)),
802803
sym::atomic_fence | sym::atomic_singlethreadfence => (0, 1, Vec::new(), tcx.types.unit),
803804

805+
sym::return_address => (0, 0, vec![], Ty::new_imm_ptr(tcx, tcx.types.unit)),
806+
804807
other => {
805808
tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span, name: other });
806809
return;

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,7 @@ symbols! {
16571657
residual,
16581658
result,
16591659
result_ffi_guarantees,
1660+
return_address,
16601661
return_position_impl_trait_in_trait,
16611662
return_type_notation,
16621663
riscv32,

library/core/src/arch.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,29 @@ pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?
7676
pub fn breakpoint() {
7777
core::intrinsics::breakpoint();
7878
}
79+
80+
/// The `core::arch::return_address!()` macro returns a pointer with an address that corresponds to the caller of the function that invoked the `return_address!()` macro.
81+
/// The pointer has no provenance, as if created by `core::ptr::without_provenance`. It cannot be used to read memory (other than ZSTs).
82+
///
83+
/// The value returned by the macro depends highly on the architecture and compiler (including any options set).
84+
/// In particular, it is allowed to be wrong (particularly if inlining is involved), or even contain a nonsense value.
85+
/// The result of this macro must not be relied upon for soundness or correctness, only for debugging purposes.
86+
///
87+
/// As a best effort, if a useful value cannot be determined (for example, due to limitations on the current codegen),
88+
/// this macro tries to return a null pointer instead of nonsense (this cannot be relied upon for correctness, however).
89+
///
90+
/// Formally, this function returns a pointer with a non-deterministic address and no provenance.
91+
///
92+
/// This is equivalent to the gcc `__builtin_return_address(0)` intrinsic (other forms of the intrinsic are not supported).
93+
/// Because the operation can be always performed by the compiler without crashing or causing undefined behaviour, invoking the macro is a safe operation.
94+
///
95+
/// ## Example
96+
/// ```
97+
/// #![feature(return_address)]
98+
///
99+
/// let addr = core::arch::return_address!();
100+
/// println!("Caller is {addr:p}");
101+
/// ```
102+
#[unstable(feature = "return_address", issue = "154966")]
103+
#[allow_internal_unstable(core_intrinsics)]
104+
pub macro return_address() {{ core::intrinsics::return_address() }}

library/core/src/char/mod.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,31 +93,31 @@ const MAX_THREE_B: u32 = 0x10000;
9393

9494
/// The highest valid code point a `char` can have, `'\u{10FFFF}'`. Use [`char::MAX`] instead.
9595
#[stable(feature = "rust1", since = "1.0.0")]
96+
#[deprecated(since = "TBD", note = "replaced by the `MAX` associated constant on `char`")]
9697
pub const MAX: char = char::MAX;
9798

98-
/// The maximum number of bytes required to [encode](char::encode_utf8) a `char` to
99-
/// UTF-8 encoding.
100-
#[unstable(feature = "char_max_len", issue = "121714")]
101-
pub const MAX_LEN_UTF8: usize = char::MAX_LEN_UTF8;
102-
103-
/// The maximum number of two-byte units required to [encode](char::encode_utf16) a `char`
104-
/// to UTF-16 encoding.
105-
#[unstable(feature = "char_max_len", issue = "121714")]
106-
pub const MAX_LEN_UTF16: usize = char::MAX_LEN_UTF16;
107-
10899
/// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
109100
/// decoding error. Use [`char::REPLACEMENT_CHARACTER`] instead.
110101
#[stable(feature = "decode_utf16", since = "1.9.0")]
102+
#[deprecated(
103+
since = "TBD",
104+
note = "replaced by the `REPLACEMENT_CHARACTER` associated constant on `char`"
105+
)]
111106
pub const REPLACEMENT_CHARACTER: char = char::REPLACEMENT_CHARACTER;
112107

113108
/// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of
114109
/// `char` and `str` methods are based on. Use [`char::UNICODE_VERSION`] instead.
115110
#[stable(feature = "unicode_version", since = "1.45.0")]
111+
#[deprecated(
112+
since = "TBD",
113+
note = "replaced by the `UNICODE_VERSION` associated constant on `char`"
114+
)]
116115
pub const UNICODE_VERSION: (u8, u8, u8) = char::UNICODE_VERSION;
117116

118117
/// Creates an iterator over the UTF-16 encoded code points in `iter`, returning
119118
/// unpaired surrogates as `Err`s. Use [`char::decode_utf16`] instead.
120119
#[stable(feature = "decode_utf16", since = "1.9.0")]
120+
#[deprecated(since = "TBD", note = "replaced by the `decode_utf16` method on `char`")]
121121
#[inline]
122122
pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
123123
self::decode::decode_utf16(iter)
@@ -126,6 +126,7 @@ pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::Into
126126
/// Converts a `u32` to a `char`. Use [`char::from_u32`] instead.
127127
#[stable(feature = "rust1", since = "1.0.0")]
128128
#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
129+
#[deprecated(since = "TBD", note = "replaced by the `from_u32` method on `char`")]
129130
#[must_use]
130131
#[inline]
131132
pub const fn from_u32(i: u32) -> Option<char> {
@@ -136,6 +137,7 @@ pub const fn from_u32(i: u32) -> Option<char> {
136137
/// instead.
137138
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
138139
#[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")]
140+
#[deprecated(since = "TBD", note = "replaced by the `from_u32_unchecked` method on `char`")]
139141
#[must_use]
140142
#[inline]
141143
pub const unsafe fn from_u32_unchecked(i: u32) -> char {
@@ -146,6 +148,7 @@ pub const unsafe fn from_u32_unchecked(i: u32) -> char {
146148
/// Converts a digit in the given radix to a `char`. Use [`char::from_digit`] instead.
147149
#[stable(feature = "rust1", since = "1.0.0")]
148150
#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
151+
#[deprecated(since = "TBD", note = "replaced by the `from_digit` method on `char`")]
149152
#[must_use]
150153
#[inline]
151154
pub const fn from_digit(num: u32, radix: u32) -> Option<char> {

library/core/src/intrinsics/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3589,3 +3589,16 @@ pub const fn va_copy<'f>(src: &VaList<'f>) -> VaList<'f> {
35893589
pub const unsafe fn va_end(ap: &mut VaList<'_>) {
35903590
/* deliberately does nothing */
35913591
}
3592+
3593+
/// Returns the return address of the caller function (after inlining) in a best-effort manner or a null pointer if it is not supported on the current backend.
3594+
/// Returning an accurate value is a quality-of-implementation concern, but no hard guarantees are
3595+
/// made about the return value: formally, the intrinsic non-deterministically returns
3596+
/// an arbitrary pointer without provenance.
3597+
///
3598+
/// Note that unlike most intrinsics, this is safe to call. This is because it only finds the return address of the immediate caller, which is guaranteed to be possible.
3599+
/// Other forms of the corresponding gcc or llvm intrinsic (which can have wildly unpredictable results or even crash at runtime) are not exposed.
3600+
#[rustc_intrinsic]
3601+
#[rustc_nounwind]
3602+
pub fn return_address() -> *const () {
3603+
core::ptr::null()
3604+
}

0 commit comments

Comments
 (0)