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; +}