about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2012-07-07 00:52:31 -0400
committerBrian Anderson <banderson@mozilla.com>2012-07-09 13:13:49 -0700
commita7f6e009446c3f0810b26bf9e3c91aefa08bd240 (patch)
tree4af360268fb2e56d63172f8723801071bb8694a8 /src
parentf3b50ae348306146e342641238c8e21cf0d545bb (diff)
Fix metadata serialization of foreign functions. Properly take the value of foreign functions from other crates to fix #1840.
Diffstat (limited to 'src')
-rw-r--r--src/rustc/metadata/decoder.rs1
-rw-r--r--src/rustc/metadata/encoder.rs2
-rw-r--r--src/rustc/middle/trans/base.rs12
-rw-r--r--src/test/auxiliary/extern-crosscrate-source.rs22
-rw-r--r--src/test/run-pass/extern-crosscrate.rs14
5 files changed, 45 insertions, 6 deletions
diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs
index 33805407860..13829a188d9 100644
--- a/src/rustc/metadata/decoder.rs
+++ b/src/rustc/metadata/decoder.rs
@@ -288,6 +288,7 @@ fn item_to_def_like(item: ebml::doc, did: ast::def_id, cnum: ast::crate_num)
       'u' { dl_def(ast::def_fn(did, ast::unsafe_fn)) }
       'f' { dl_def(ast::def_fn(did, ast::impure_fn)) }
       'p' { dl_def(ast::def_fn(did, ast::pure_fn)) }
+      'F' { dl_def(ast::def_fn(did, ast::extern_fn)) }
       'y' { dl_def(ast::def_ty(did)) }
       't' { dl_def(ast::def_ty(did)) }
       'm' { dl_def(ast::def_mod(did)) }
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index 46a3cd84be3..1e50f1168c7 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -527,7 +527,7 @@ fn purity_fn_family(p: purity) -> char {
       unsafe_fn { 'u' }
       pure_fn { 'p' }
       impure_fn { 'f' }
-      extern_fn { 'c' }
+      extern_fn { 'F' }
     }
 }
 
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 459b1403845..5534140ae72 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -2392,16 +2392,18 @@ fn lval_static_fn_inner(bcx: block, fn_id: ast::def_id, id: ast::node_id,
             ccx, node_id_type(bcx, id))));
     }
 
-    // FIXME: Need to support extern-ABI functions (#1840)
-    if fn_id.crate == ast::local_crate {
-        alt bcx.tcx().def_map.find(id) {
-          some(ast::def_fn(_, ast::extern_fn)) {
+    alt ty::get(tpt.ty).struct {
+      ty::ty_fn(fn_ty) {
+        alt fn_ty.purity {
+          ast::extern_fn {
             // Extern functions are just opaque pointers
             let val = PointerCast(bcx, val, T_ptr(T_i8()));
             ret lval_no_env(bcx, val, owned_imm);
           }
-          _ { }
+          _ { /* fall through */ }
         }
+      }
+      _ { /* fall through */ }
     }
 
     ret {bcx: bcx, val: val, kind: owned, env: null_env};
diff --git a/src/test/auxiliary/extern-crosscrate-source.rs b/src/test/auxiliary/extern-crosscrate-source.rs
new file mode 100644
index 00000000000..55d08a0d0f4
--- /dev/null
+++ b/src/test/auxiliary/extern-crosscrate-source.rs
@@ -0,0 +1,22 @@
+#[link(name = "externcallback",
+       vers = "0.1")];
+
+#[crate_type = "lib"];
+
+extern mod rustrt {
+    fn rust_dbg_call(cb: *u8,
+                     data: libc::uintptr_t) -> libc::uintptr_t;
+}
+
+fn fact(n: uint) -> uint {
+    #debug("n = %?", n);
+    rustrt::rust_dbg_call(cb, n)
+}
+
+extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t {
+    if data == 1u {
+        data
+    } else {
+        fact(data - 1u) * data
+    }
+}
diff --git a/src/test/run-pass/extern-crosscrate.rs b/src/test/run-pass/extern-crosscrate.rs
new file mode 100644
index 00000000000..f3338475912
--- /dev/null
+++ b/src/test/run-pass/extern-crosscrate.rs
@@ -0,0 +1,14 @@
+//aux-build:extern-crosscrate-source.rs
+
+use externcallback(vers = "0.1");
+
+fn fact(n: uint) -> uint {
+    #debug("n = %?", n);
+    externcallback::rustrt::rust_dbg_call(externcallback::cb, n)
+}
+
+fn main() {
+    let result = fact(10u);
+    #debug("result = %?", result);
+    assert result == 3628800u;
+}