#[stable(feature = "rust1", since = "1.0.0")]
pub fn transmute<T, U>(e: T) -> U;
+ /// Gives the address for the return value of the enclosing function.
+ ///
+ /// Using this intrinsic in a function that does not use an out pointer
+ /// will trigger a compiler error.
+ pub fn return_address() -> *const u8;
+
/// Returns `true` if the actual type given as `T` requires drop
/// glue; returns `false` if the actual type provided for `T`
/// implements `Copy`.
register_long_diagnostics! {
+E0510: r##"
+`return_address` was used in an invalid context. Erroneous code example:
+
+```ignore
+#![feature(intrinsics)]
+
+extern "rust-intrinsic" {
+ fn return_address() -> *const u8;
+}
+
+unsafe fn by_value() -> i32 {
+ let _ = return_address();
+ // error: invalid use of `return_address` intrinsic: function does
+ // not use out pointer
+ 0
+}
+```
+
+Return values may be stored in a return register(s) or written into a so-called
+out pointer. In case the returned value is too big (this is
+target-ABI-dependent and generally not portable or future proof) to fit into
+the return register(s), the compiler will return the value by writing it into
+space allocated in the caller's stack frame. Example:
+
+```
+#![feature(intrinsics)]
+
+extern "rust-intrinsic" {
+ fn return_address() -> *const u8;
+}
+
+unsafe fn by_pointer() -> String {
+ let _ = return_address();
+ String::new() // ok!
+}
+```
+"##,
+
E0511: r##"
Invalid monomorphization of an intrinsic function was used. Erroneous code
example:
},
+
+ (_, "return_address") => {
+ if !fcx.fn_ty.ret.is_indirect() {
+ span_err!(tcx.sess, span, E0510,
+ "invalid use of `return_address` intrinsic: function \
+ does not use out pointer");
+ C_null(Type::i8p(ccx))
+ } else {
+ PointerCast(bcx, llvm::get_param(fcx.llfn, 0), Type::i8p(ccx))
+ }
+ }
+
(_, "discriminant_value") => {
let val_ty = substs.types.get(FnSpace, 0);
match val_ty.sty {
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" =>
(1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
+ "return_address" => (0, vec![], tcx.mk_imm_ptr(tcx.types.u8)),
+
"assume" => (0, vec![tcx.types.bool], tcx.mk_nil()),
"discriminant_value" => (1, vec![
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(warnings)]
+#![feature(intrinsics)]
+
+extern "rust-intrinsic" {
+ fn return_address() -> *const u8;
+}
+
+unsafe fn f() { let _ = return_address(); }
+//~^ ERROR invalid use of `return_address` intrinsic: function does not use out pointer
+
+unsafe fn g() -> isize { let _ = return_address(); 0 }
+//~^ ERROR invalid use of `return_address` intrinsic: function does not use out pointer
+
+fn main() {}
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+#![feature(intrinsics)]
+
+use std::ptr;
+
+struct Point {
+ x: f32,
+ y: f32,
+ z: f32,
+}
+
+extern "rust-intrinsic" {
+ fn return_address() -> *const u8;
+}
+
+fn f(result: &mut usize) -> Point {
+ unsafe {
+ *result = return_address() as usize;
+ Point {
+ x: 1.0,
+ y: 2.0,
+ z: 3.0,
+ }
+ }
+
+}
+
+fn main() {
+ let mut intrinsic_reported_address = 0;
+ let pt = f(&mut intrinsic_reported_address);
+ let actual_address = &pt as *const Point as usize;
+ assert_eq!(intrinsic_reported_address, actual_address);
+}