Skip to content

Commit f698cd3

Browse files
committed
Revert "Remove the return_address intrinsic."
This reverts commit b30134d.
1 parent c2b56fb commit f698cd3

File tree

6 files changed

+125
-0
lines changed

6 files changed

+125
-0
lines changed

src/libcore/intrinsics.rs

+6
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,12 @@ extern "rust-intrinsic" {
293293
#[stable(feature = "rust1", since = "1.0.0")]
294294
pub fn transmute<T, U>(e: T) -> U;
295295

296+
/// Gives the address for the return value of the enclosing function.
297+
///
298+
/// Using this intrinsic in a function that does not use an out pointer
299+
/// will trigger a compiler error.
300+
pub fn return_address() -> *const u8;
301+
296302
/// Returns `true` if the actual type given as `T` requires drop
297303
/// glue; returns `false` if the actual type provided for `T`
298304
/// implements `Copy`.

src/librustc_trans/diagnostics.rs

+38
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,44 @@
1212

1313
register_long_diagnostics! {
1414

15+
E0510: r##"
16+
`return_address` was used in an invalid context. Erroneous code example:
17+
18+
```ignore
19+
#![feature(intrinsics)]
20+
21+
extern "rust-intrinsic" {
22+
fn return_address() -> *const u8;
23+
}
24+
25+
unsafe fn by_value() -> i32 {
26+
let _ = return_address();
27+
// error: invalid use of `return_address` intrinsic: function does
28+
// not use out pointer
29+
0
30+
}
31+
```
32+
33+
Return values may be stored in a return register(s) or written into a so-called
34+
out pointer. In case the returned value is too big (this is
35+
target-ABI-dependent and generally not portable or future proof) to fit into
36+
the return register(s), the compiler will return the value by writing it into
37+
space allocated in the caller's stack frame. Example:
38+
39+
```
40+
#![feature(intrinsics)]
41+
42+
extern "rust-intrinsic" {
43+
fn return_address() -> *const u8;
44+
}
45+
46+
unsafe fn by_pointer() -> String {
47+
let _ = return_address();
48+
String::new() // ok!
49+
}
50+
```
51+
"##,
52+
1553
E0511: r##"
1654
Invalid monomorphization of an intrinsic function was used. Erroneous code
1755
example:

src/librustc_trans/intrinsic.rs

+12
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,18 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
617617

618618
},
619619

620+
621+
(_, "return_address") => {
622+
if !fcx.fn_ty.ret.is_indirect() {
623+
span_err!(tcx.sess, span, E0510,
624+
"invalid use of `return_address` intrinsic: function \
625+
does not use out pointer");
626+
C_null(Type::i8p(ccx))
627+
} else {
628+
PointerCast(bcx, llvm::get_param(fcx.llfn, 0), Type::i8p(ccx))
629+
}
630+
}
631+
620632
(_, "discriminant_value") => {
621633
let val_ty = substs.types.get(FnSpace, 0);
622634
match val_ty.sty {

src/librustc_typeck/check/intrinsic.rs

+2
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
275275
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" =>
276276
(1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
277277

278+
"return_address" => (0, vec![], tcx.mk_imm_ptr(tcx.types.u8)),
279+
278280
"assume" => (0, vec![tcx.types.bool], tcx.mk_nil()),
279281

280282
"discriminant_value" => (1, vec![
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(warnings)]
12+
#![feature(intrinsics)]
13+
14+
extern "rust-intrinsic" {
15+
fn return_address() -> *const u8;
16+
}
17+
18+
unsafe fn f() { let _ = return_address(); }
19+
//~^ ERROR invalid use of `return_address` intrinsic: function does not use out pointer
20+
21+
unsafe fn g() -> isize { let _ = return_address(); 0 }
22+
//~^ ERROR invalid use of `return_address` intrinsic: function does not use out pointer
23+
24+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
12+
#![feature(intrinsics)]
13+
14+
use std::ptr;
15+
16+
struct Point {
17+
x: f32,
18+
y: f32,
19+
z: f32,
20+
}
21+
22+
extern "rust-intrinsic" {
23+
fn return_address() -> *const u8;
24+
}
25+
26+
fn f(result: &mut usize) -> Point {
27+
unsafe {
28+
*result = return_address() as usize;
29+
Point {
30+
x: 1.0,
31+
y: 2.0,
32+
z: 3.0,
33+
}
34+
}
35+
36+
}
37+
38+
fn main() {
39+
let mut intrinsic_reported_address = 0;
40+
let pt = f(&mut intrinsic_reported_address);
41+
let actual_address = &pt as *const Point as usize;
42+
assert_eq!(intrinsic_reported_address, actual_address);
43+
}

0 commit comments

Comments
 (0)