mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-16 21:15:18 +03:00
Rollup merge of #154972 - chorman0773:return_address, r=Mark-Simulacrum
Implement `core::arch::return_address` and tests Tracking issue: rust-lang/rust#154966 Implements libs-team#768
This commit is contained in:
@@ -1523,6 +1523,12 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
||||
fx.bcx.set_cold_block(fx.bcx.current_block().unwrap());
|
||||
}
|
||||
|
||||
sym::return_address => {
|
||||
let val = fx.bcx.ins().get_return_address(fx.pointer_type);
|
||||
let val = CValue::by_val(val, ret.layout());
|
||||
ret.write_cvalue(fx, val);
|
||||
}
|
||||
|
||||
// Unimplemented intrinsics must have a fallback body. The fallback body is obtained
|
||||
// by converting the `InstanceKind::Intrinsic` to an `InstanceKind::Item`.
|
||||
_ => {
|
||||
|
||||
@@ -849,6 +849,22 @@ fn codegen_intrinsic_call(
|
||||
}
|
||||
}
|
||||
|
||||
sym::return_address => {
|
||||
match self.sess().target.arch {
|
||||
// Expand this list as needed
|
||||
| Arch::Wasm32
|
||||
| Arch::Wasm64 => {
|
||||
let ty = self.type_ptr();
|
||||
self.const_null(ty)
|
||||
}
|
||||
_ => {
|
||||
let ty = self.type_ix(32);
|
||||
let val = self.const_int(ty, 0);
|
||||
self.call_intrinsic("llvm.returnaddress", &[], &[val])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
debug!("unknown intrinsic '{}' -- falling back to default body", name);
|
||||
// Call the fallback body instead of generating the intrinsic code
|
||||
|
||||
@@ -121,7 +121,8 @@ pub fn codegen_intrinsic_call(
|
||||
| sym::contract_checks
|
||||
| sym::atomic_fence
|
||||
| sym::atomic_singlethreadfence
|
||||
| sym::caller_location => {}
|
||||
| sym::caller_location
|
||||
| sym::return_address => {}
|
||||
_ => {
|
||||
span_bug!(
|
||||
span,
|
||||
|
||||
@@ -180,6 +180,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
|
||||
| sym::ptr_guaranteed_cmp
|
||||
| sym::ptr_mask
|
||||
| sym::ptr_metadata
|
||||
| sym::return_address
|
||||
| sym::rotate_left
|
||||
| sym::rotate_right
|
||||
| sym::round_ties_even_f16
|
||||
@@ -793,6 +794,8 @@ pub(crate) fn check_intrinsic_type(
|
||||
| sym::atomic_xor => (2, 1, vec![Ty::new_mut_ptr(tcx, param(0)), param(1)], param(0)),
|
||||
sym::atomic_fence | sym::atomic_singlethreadfence => (0, 1, Vec::new(), tcx.types.unit),
|
||||
|
||||
sym::return_address => (0, 0, vec![], Ty::new_imm_ptr(tcx, tcx.types.unit)),
|
||||
|
||||
other => {
|
||||
tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span, name: other });
|
||||
return;
|
||||
|
||||
@@ -1663,6 +1663,7 @@
|
||||
residual,
|
||||
result,
|
||||
result_ffi_guarantees,
|
||||
return_address,
|
||||
return_position_impl_trait_in_trait,
|
||||
return_type_notation,
|
||||
riscv32,
|
||||
|
||||
@@ -76,3 +76,33 @@
|
||||
pub fn breakpoint() {
|
||||
core::intrinsics::breakpoint();
|
||||
}
|
||||
|
||||
/// 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.
|
||||
/// The pointer has no provenance, as if created by `core::ptr::without_provenance`. It cannot be used to read memory (other than ZSTs).
|
||||
///
|
||||
/// The value returned by the macro depends highly on the architecture and compiler (including any options set).
|
||||
/// In particular, it is allowed to be wrong (particularly if inlining is involved), or even contain a nonsense value.
|
||||
/// The result of this macro must not be relied upon for soundness or correctness, only for debugging purposes.
|
||||
///
|
||||
/// As a best effort, if a useful value cannot be determined (for example, due to limitations on the current codegen),
|
||||
/// this macro tries to return a null pointer instead of nonsense (this cannot be relied upon for correctness, however).
|
||||
///
|
||||
/// Formally, this function returns a pointer with a non-deterministic address and no provenance.
|
||||
///
|
||||
/// This is equivalent to the gcc `__builtin_return_address(0)` intrinsic (other forms of the intrinsic are not supported).
|
||||
/// Because the operation can be always performed by the compiler without crashing or causing undefined behaviour, invoking the macro is a safe operation.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// #![feature(return_address)]
|
||||
///
|
||||
/// # fn run_test() {
|
||||
/// let addr = core::arch::return_address!();
|
||||
/// println!("Caller is {addr:p}");
|
||||
/// # }
|
||||
/// # #[cfg(not(miri))] // FIXME: Figure out how to make miri work before stabilizing this macro
|
||||
/// # run_test()
|
||||
/// ```
|
||||
#[unstable(feature = "return_address", issue = "154966")]
|
||||
#[allow_internal_unstable(core_intrinsics)]
|
||||
pub macro return_address() {{ core::intrinsics::return_address() }}
|
||||
|
||||
@@ -3598,3 +3598,16 @@ pub const fn va_copy<'f>(src: &VaList<'f>) -> VaList<'f> {
|
||||
pub const unsafe fn va_end(ap: &mut VaList<'_>) {
|
||||
/* deliberately does nothing */
|
||||
}
|
||||
|
||||
/// 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.
|
||||
/// Returning an accurate value is a quality-of-implementation concern, but no hard guarantees are
|
||||
/// made about the return value: formally, the intrinsic non-deterministically returns
|
||||
/// an arbitrary pointer without provenance.
|
||||
///
|
||||
/// 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.
|
||||
/// Other forms of the corresponding gcc or llvm intrinsic (which can have wildly unpredictable results or even crash at runtime) are not exposed.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub fn return_address() -> *const () {
|
||||
core::ptr::null()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
//@ ignore-wasm
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(core_intrinsics, return_address)]
|
||||
|
||||
// CHECK-LABEL: @call_return_address_intrinsic
|
||||
#[no_mangle]
|
||||
#[inline(never)]
|
||||
pub fn call_return_address_intrinsic() -> *const () {
|
||||
// CHECK: call ptr @llvm.returnaddress(i32 0)
|
||||
core::intrinsics::return_address()
|
||||
}
|
||||
Reference in New Issue
Block a user