about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2014-08-04 11:48:26 -0700
committerLuqman Aden <me@luqman.ca>2014-08-11 19:20:10 -0700
commit9dac85f92daa094f94f124fd06cfeb5339d48772 (patch)
tree45465497869bcf25378b43be0b40469c5a526155 /src
parentd3028138889d8eb2aaa3dce899d556f8bbf04d13 (diff)
downloadrust-9dac85f92daa094f94f124fd06cfeb5339d48772.tar.gz
rust-9dac85f92daa094f94f124fd06cfeb5339d48772.zip
librustc: Add an intrinsic to retrieve the return pointer of a function.
This is needed for some GC stuff in Servo.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/trans/intrinsic.rs6
-rw-r--r--src/librustc/middle/typeck/check/mod.rs2
-rw-r--r--src/test/run-pass/intrinsic-return-address.rs43
3 files changed, 51 insertions, 0 deletions
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs
index fb420a4035d..154f2b122ab 100644
--- a/src/librustc/middle/trans/intrinsic.rs
+++ b/src/librustc/middle/trans/intrinsic.rs
@@ -425,6 +425,12 @@ pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId,
             with_overflow_intrinsic(bcx, "llvm.umul.with.overflow.i64", ret_ty,
                                     *llargs.get(0), *llargs.get(1)),
 
+        (_, "return_address") => {
+            PointerCast(bcx,
+                        bcx.fcx.llretptr.get().unwrap(),
+                        Type::i8p(bcx.ccx()))
+        }
+
         // This requires that atomic intrinsics follow a specific naming pattern:
         // "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
         (_, name) if name.starts_with("atomic_") => {
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 787a4bebc55..aa38ff68f24 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -4986,6 +4986,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                 (0, vec!(ty::mk_u64(), ty::mk_u64()),
                 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
 
+            "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
+
             ref other => {
                 span_err!(tcx.sess, it.span, E0093,
                     "unrecognized intrinsic function: `{}`", *other);
diff --git a/src/test/run-pass/intrinsic-return-address.rs b/src/test/run-pass/intrinsic-return-address.rs
new file mode 100644
index 00000000000..a28a79d306b
--- /dev/null
+++ b/src/test/run-pass/intrinsic-return-address.rs
@@ -0,0 +1,43 @@
+// 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 uint) -> Point {
+    unsafe {
+        *result = return_address() as uint;
+        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 uint;
+    assert_eq!(intrinsic_reported_address, actual_address);
+}
+