From 78511a4830505dbda264f2658a481a625f16a696 Mon Sep 17 00:00:00 2001 From: Graham Fawcett Date: Thu, 15 Dec 2011 15:25:29 -0500 Subject: [PATCH 1/2] implement #[nolink]; deprecate #[link_name = ""]; note in stdlib to remove empty link_name. Can't remove them from stdlib until the snapshotted compiler supports #[nolink]. --- doc/tutorial/ffi.md | 4 ++-- src/comp/metadata/creader.rs | 8 ++++++++ src/comp/metadata/cstore.rs | 1 - src/libstd/linux_os.rs | 3 ++- src/libstd/macos_os.rs | 5 +++-- src/libstd/win32_os.rs | 3 ++- src/test/bench/shootout-nbody.rs | 2 +- src/test/compile-fail/empty-linkname.rs | 5 +++++ src/test/run-pass/bind-native-fn.rs | 2 +- src/test/run-pass/binops.rs | 2 +- src/test/run-pass/c-stack-returning-int64.rs | 2 +- src/test/run-pass/import-glob-1.rs | 2 +- src/test/run-pass/native-fn-linkname.rs | 2 +- src/test/run-pass/native-opaque-type.rs | 2 +- src/test/run-pass/native2.rs | 8 ++++---- src/test/stdtest/c_vec.rs | 2 +- 16 files changed, 34 insertions(+), 19 deletions(-) create mode 100644 src/test/compile-fail/empty-linkname.rs diff --git a/doc/tutorial/ffi.md b/doc/tutorial/ffi.md index 7b90f64a6ba56..248da6edef488 100644 --- a/doc/tutorial/ffi.md +++ b/doc/tutorial/ffi.md @@ -189,7 +189,7 @@ microsecond-resolution timer. use std; type timeval = {mutable tv_sec: u32, mutable tv_usec: u32}; - #[link_name = ""] + #[nolink] native mod libc { fn gettimeofday(tv: *timeval, tz: *()) -> i32; } @@ -199,7 +199,7 @@ microsecond-resolution timer. ret (x.tv_sec as u64) * 1000_000_u64 + (x.tv_usec as u64); } -The `#[link_name = ""]` sets the name of the native module to the +The `#[nolink]` sets the name of the native module to the empty string to prevent the rust compiler from trying to link it. The standard C library is already linked with Rust programs. diff --git a/src/comp/metadata/creader.rs b/src/comp/metadata/creader.rs index 34da777a86435..a79329ea5a3dc 100644 --- a/src/comp/metadata/creader.rs +++ b/src/comp/metadata/creader.rs @@ -57,12 +57,20 @@ fn visit_item(e: env, i: @ast::item) { } either::left(msg) { e.sess.span_fatal(i.span, msg); } } + let cstore = e.sess.get_cstore(); let native_name = i.ident; + if vec::len(attr::find_attrs_by_name(i.attrs, "nolink")) > 0u { + ret; + } alt attr::get_meta_item_value_str_by_name(i.attrs, "link_name") { some(nn) { native_name = nn; } none. { } } + if native_name == "" { + e.sess.span_fatal(i.span, + "empty #[link_name] not allowed; use #[nolink]."); + } if !cstore::add_used_library(cstore, native_name) { ret; } for a: ast::attribute in attr::find_attrs_by_name(i.attrs, "link_args") { diff --git a/src/comp/metadata/cstore.rs b/src/comp/metadata/cstore.rs index de74591c814ee..8bad609e436c9 100644 --- a/src/comp/metadata/cstore.rs +++ b/src/comp/metadata/cstore.rs @@ -93,7 +93,6 @@ fn add_used_library(cstore: cstore, lib: str) -> bool { if lib == "" { ret false; } if vec::member(lib, p(cstore).used_libraries) { ret false; } - p(cstore).used_libraries += [lib]; ret true; } diff --git a/src/libstd/linux_os.rs b/src/libstd/linux_os.rs index 8528057ed98f7..e5b13a7cfc2a6 100644 --- a/src/libstd/linux_os.rs +++ b/src/libstd/linux_os.rs @@ -24,7 +24,8 @@ export fsync_fd; // FIXME Somehow merge stuff duplicated here and macosx_os.rs. Made difficult // by https://github.com/graydon/rust/issues#issue/268 -#[link_name = ""] +#[link_name = ""] // FIXME remove after #[nolink] is snapshotted +#[nolink] #[abi = "cdecl"] native mod libc { fn read(fd: fd_t, buf: *u8, count: size_t) -> ssize_t; diff --git a/src/libstd/macos_os.rs b/src/libstd/macos_os.rs index 72afcc234b3cb..37a7d0ff95f2f 100644 --- a/src/libstd/macos_os.rs +++ b/src/libstd/macos_os.rs @@ -18,7 +18,7 @@ export fsync_fd; // FIXME Refactor into unix_os module or some such. Doesn't // seem to work right now. -#[link_name = ""] +#[nolink] #[abi = "cdecl"] native mod libc { fn read(fd: fd_t, buf: *u8, count: size_t) -> ssize_t; @@ -118,7 +118,8 @@ native mod rustrt { fn getcwd() -> str { ret rustrt::rust_getcwd(); } -#[link_name = ""] +#[link_name = ""] // FIXME remove after #[nolink] is snapshotted +#[nolink] #[abi = "cdecl"] native mod mac_libc { fn _NSGetExecutablePath(buf: str::sbuf, diff --git a/src/libstd/win32_os.rs b/src/libstd/win32_os.rs index 439a79ec7acd5..825f4ffa0ebd2 100644 --- a/src/libstd/win32_os.rs +++ b/src/libstd/win32_os.rs @@ -2,7 +2,8 @@ import core::option; import ctypes::*; #[abi = "cdecl"] -#[link_name = ""] +#[link_name = ""] // FIXME remove after #[nolink] is snapshotted +#[nolink] native mod libc { fn read(fd: fd_t, buf: *u8, count: size_t) -> ssize_t; fn write(fd: fd_t, buf: *u8, count: size_t) -> ssize_t; diff --git a/src/test/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index a560e6e1d7a9f..cf4daa6b2ec0d 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -2,7 +2,7 @@ // http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=java #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod llvm { fn sqrt(n: float) -> float; } diff --git a/src/test/compile-fail/empty-linkname.rs b/src/test/compile-fail/empty-linkname.rs new file mode 100644 index 0000000000000..1e04913884bf0 --- /dev/null +++ b/src/test/compile-fail/empty-linkname.rs @@ -0,0 +1,5 @@ +// error-pattern:empty #[link_name] not allowed; use #[nolink]. + +#[link_name = ""] +native mod foo { +} diff --git a/src/test/run-pass/bind-native-fn.rs b/src/test/run-pass/bind-native-fn.rs index aab3ba2dc7564..2984f97813b66 100644 --- a/src/test/run-pass/bind-native-fn.rs +++ b/src/test/run-pass/bind-native-fn.rs @@ -5,7 +5,7 @@ use std; import str; import ctypes::*; -#[link_name = ""] +#[nolink] native mod libc { fn write(fd: c_int, buf: *u8, nbyte: size_t); } diff --git a/src/test/run-pass/binops.rs b/src/test/run-pass/binops.rs index 3eedf7f48ca34..56469dbb17262 100644 --- a/src/test/run-pass/binops.rs +++ b/src/test/run-pass/binops.rs @@ -118,7 +118,7 @@ fn test_fn() { } #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod test { fn do_gc(); fn unsupervise(); diff --git a/src/test/run-pass/c-stack-returning-int64.rs b/src/test/run-pass/c-stack-returning-int64.rs index 879db89b71357..66c79290e4726 100644 --- a/src/test/run-pass/c-stack-returning-int64.rs +++ b/src/test/run-pass/c-stack-returning-int64.rs @@ -2,7 +2,7 @@ use std; import str; #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod libc { fn atol(x: str::sbuf) -> int; fn atoll(x: str::sbuf) -> i64; diff --git a/src/test/run-pass/import-glob-1.rs b/src/test/run-pass/import-glob-1.rs index e40d6cbb9cc23..24a15e284d4e9 100644 --- a/src/test/run-pass/import-glob-1.rs +++ b/src/test/run-pass/import-glob-1.rs @@ -21,7 +21,7 @@ mod a1 { mod a2 { // | | | #[abi = "cdecl"] - #[link_name = ""] + #[nolink] native mod b1 { // | | | import a1::b2::*; diff --git a/src/test/run-pass/native-fn-linkname.rs b/src/test/run-pass/native-fn-linkname.rs index 98f429f8cb0dc..72d0ab01f9661 100644 --- a/src/test/run-pass/native-fn-linkname.rs +++ b/src/test/run-pass/native-fn-linkname.rs @@ -3,7 +3,7 @@ use std; import vec; import str; -#[link_name = ""] +#[nolink] #[abi = "cdecl"] native mod libc { #[link_name = "strlen"] diff --git a/src/test/run-pass/native-opaque-type.rs b/src/test/run-pass/native-opaque-type.rs index e8df623d1b870..e91b4e684b763 100644 --- a/src/test/run-pass/native-opaque-type.rs +++ b/src/test/run-pass/native-opaque-type.rs @@ -1,7 +1,7 @@ #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod libc { type file_handle; } diff --git a/src/test/run-pass/native2.rs b/src/test/run-pass/native2.rs index 07cb455cf0fe0..359ce18090f39 100644 --- a/src/test/run-pass/native2.rs +++ b/src/test/run-pass/native2.rs @@ -6,21 +6,21 @@ native mod rustrt { } #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod bar { } #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod zed { } #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod libc { fn write(fd: int, buf: *u8, count: uint) -> int; } #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod baz { } fn main(args: [str]) { } diff --git a/src/test/stdtest/c_vec.rs b/src/test/stdtest/c_vec.rs index d196a7baa3b29..65a6fc9c0bee1 100644 --- a/src/test/stdtest/c_vec.rs +++ b/src/test/stdtest/c_vec.rs @@ -5,7 +5,7 @@ use std; import std::c_vec::*; import ctypes::*; -#[link_name = ""] +#[nolink] #[abi = "cdecl"] native mod libc { fn malloc(n: size_t) -> *mutable u8; From 7ad4e73d514bd2867f70ada5f98bcd6d3be2e90c Mon Sep 17 00:00:00 2001 From: Graham Fawcett Date: Fri, 16 Dec 2011 11:04:11 -0500 Subject: [PATCH 2/2] allow #[link_args] with #[nolink]. For now, fail if two modules link same lib, and second has link_args. I think it should undefined to have multiple modules that link in the same library, but provide different link arguments. Unfortunately we don't track link_args by module -- they are just appended as discovered into the crate store -- but for now, it should be an error to provide link_args on a module that's already been included (with or without link_args). --- src/comp/metadata/creader.rs | 33 +++++++++++-------- src/comp/metadata/cstore.rs | 2 +- .../compile-fail/nolink-with-link-args.rs | 11 +++++++ src/test/compile-fail/redundant-link-args.rs | 17 ++++++++++ 4 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 src/test/compile-fail/nolink-with-link-args.rs create mode 100644 src/test/compile-fail/redundant-link-args.rs diff --git a/src/comp/metadata/creader.rs b/src/comp/metadata/creader.rs index a79329ea5a3dc..9f74f7afece11 100644 --- a/src/comp/metadata/creader.rs +++ b/src/comp/metadata/creader.rs @@ -60,23 +60,28 @@ fn visit_item(e: env, i: @ast::item) { let cstore = e.sess.get_cstore(); let native_name = i.ident; - if vec::len(attr::find_attrs_by_name(i.attrs, "nolink")) > 0u { - ret; - } - alt attr::get_meta_item_value_str_by_name(i.attrs, "link_name") { - some(nn) { native_name = nn; } - none. { } + let already_added = false; + if vec::len(attr::find_attrs_by_name(i.attrs, "nolink")) == 0u { + alt attr::get_meta_item_value_str_by_name(i.attrs, "link_name") { + some(nn) { native_name = nn; } + none. { } + } + if native_name == "" { + e.sess.span_fatal(i.span, + "empty #[link_name] not allowed; use #[nolink]."); + } + already_added = !cstore::add_used_library(cstore, native_name); } - if native_name == "" { - e.sess.span_fatal(i.span, - "empty #[link_name] not allowed; use #[nolink]."); + let link_args = attr::find_attrs_by_name(i.attrs, "link_args"); + if vec::len(link_args) > 0u && already_added { + e.sess.span_fatal(i.span, "library '" + native_name + + "' already added: can't specify link_args."); } - if !cstore::add_used_library(cstore, native_name) { ret; } - for a: ast::attribute in - attr::find_attrs_by_name(i.attrs, "link_args") { - + for a: ast::attribute in link_args { alt attr::get_meta_item_value_str(attr::attr_meta(a)) { - some(linkarg) { cstore::add_used_link_args(cstore, linkarg); } + some(linkarg) { + cstore::add_used_link_args(cstore, linkarg); + } none. {/* fallthrough */ } } } diff --git a/src/comp/metadata/cstore.rs b/src/comp/metadata/cstore.rs index 8bad609e436c9..e0c0d49348df4 100644 --- a/src/comp/metadata/cstore.rs +++ b/src/comp/metadata/cstore.rs @@ -90,7 +90,7 @@ fn get_used_crate_files(cstore: cstore) -> [str] { } fn add_used_library(cstore: cstore, lib: str) -> bool { - if lib == "" { ret false; } + assert lib != ""; if vec::member(lib, p(cstore).used_libraries) { ret false; } p(cstore).used_libraries += [lib]; diff --git a/src/test/compile-fail/nolink-with-link-args.rs b/src/test/compile-fail/nolink-with-link-args.rs new file mode 100644 index 0000000000000..07efff7571c33 --- /dev/null +++ b/src/test/compile-fail/nolink-with-link-args.rs @@ -0,0 +1,11 @@ +// error-pattern:aFdEfSeVEE + +/* We're testing that link_args are indeed passed when nolink is specified. +So we try to compile with junk link_args and make sure they are visible in +the compiler output. */ + +#[link_args = "aFdEfSeVEEE"] +#[nolink] +native mod m1 { } + +fn main() { } \ No newline at end of file diff --git a/src/test/compile-fail/redundant-link-args.rs b/src/test/compile-fail/redundant-link-args.rs new file mode 100644 index 0000000000000..ca06125880e3d --- /dev/null +++ b/src/test/compile-fail/redundant-link-args.rs @@ -0,0 +1,17 @@ +// error-pattern:library 'm' already added: can't specify link_args. + +/* I think it should undefined to have multiple modules that link in the same + library, but provide different link arguments. Unfortunately we don't track + link_args by module -- they are just appended as discovered into the crate + store -- but for now, it should be an error to provide link_args on a module + that's already been included (with or without link_args). */ + +#[link_name= "m"] +#[link_args="-foo"] // this could have been elided. +native mod m1 { +} + +#[link_name= "m"] +#[link_args="-bar"] // this is the actual error trigger. +native mod m2 { +}