]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #30504 - mitaa:rdoc_root, r=alexcrichton
authorbors <bors@rust-lang.org>
Wed, 23 Dec 2015 06:20:02 +0000 (06:20 +0000)
committerbors <bors@rust-lang.org>
Wed, 23 Dec 2015 06:20:02 +0000 (06:20 +0000)
fixes #30327

22 files changed:
configure
mk/crates.mk
mk/rt.mk
src/liballoc_jemalloc/lib.rs
src/librustc/session/config.rs
src/librustc_back/target/aarch64_unknown_linux_gnu.rs
src/librustc_back/target/apple_base.rs
src/librustc_back/target/apple_ios_base.rs
src/librustc_back/target/arm_linux_androideabi.rs
src/librustc_back/target/linux_base.rs
src/librustc_back/target/mod.rs
src/librustc_driver/driver.rs
src/libstd/lib.rs
src/libstd/rtdeps.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/unix/os.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/libsyntax/feature_gate.rs
src/libtest/lib.rs
src/rt/rust_android_dummy.c [deleted file]
src/rt/rust_builtin.c [deleted file]

index 6e2d3060bc3c0d66d091cd3fc473322346e93a89..c4944f53463506d65df6822e472b6f1063763c16 100755 (executable)
--- a/configure
+++ b/configure
@@ -587,7 +587,7 @@ opt fast-make 0 "use .gitmodules as timestamp for submodule deps"
 opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds"
 opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
 opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
-opt rpath 0 "build rpaths into rustc itself"
+opt rpath 1 "build rpaths into rustc itself"
 opt stage0-landing-pads 1 "enable landing pads during bootstrap with stage0"
 # This is used by the automation to produce single-target nightlies
 opt dist-host-only 0 "only install bins for the host architecture"
index 2b66baed45b9487a80af3d5e576ab9b3b9e17075..2597c724da96fd7ad4aa096d7633bc6e3bc80635 100644 (file)
@@ -71,7 +71,7 @@ DEPS_rustc_bitflags := core
 DEPS_rustc_unicode := core
 
 DEPS_std := core libc rand alloc collections rustc_unicode \
-       native:rust_builtin native:backtrace \
+       native:backtrace \
        alloc_system
 DEPS_arena := std
 DEPS_glob := std
index 9d12bf39825a6f0e56a702b79d7544fe63157f50..9dbbcbebb979d34a870b47e63c2c1572267f8e27 100644 (file)
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -35,7 +35,7 @@
 # that's per-target so you're allowed to conditionally add files based on the
 # target.
 ################################################################################
-NATIVE_LIBS := rust_builtin hoedown miniz rust_test_helpers
+NATIVE_LIBS := hoedown miniz rust_test_helpers
 
 # $(1) is the target triple
 define NATIVE_LIBRARIES
@@ -50,8 +50,6 @@ NATIVE_DEPS_hoedown_$(1) := hoedown/src/autolink.c \
                        hoedown/src/stack.c \
                        hoedown/src/version.c
 NATIVE_DEPS_miniz_$(1) = miniz.c
-NATIVE_DEPS_rust_builtin_$(1) := rust_builtin.c \
-                       rust_android_dummy.c
 NATIVE_DEPS_rust_test_helpers_$(1) := rust_test_helpers.c
 
 ################################################################################
index 413eac3cf7942fd7838da275c98bebb46cf155f8..eaaa9391d3115e2667e6f6deab6c977257efcf64 100644 (file)
@@ -108,3 +108,14 @@ pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
     let flags = align_to_flags(align);
     unsafe { je_nallocx(size as size_t, flags) as usize }
 }
+
+// These symbols are used by jemalloc on android but the really old android
+// we're building on doesn't have them defined, so just make sure the symbols
+// are available.
+#[no_mangle]
+#[cfg(target_os = "android")]
+pub extern fn pthread_atfork(_prefork: *mut u8,
+                             _postfork_parent: *mut u8,
+                             _postfork_child: *mut u8) -> i32 {
+    0
+}
index e33fe9570c024f9bfaac483a1da7c47776a4834b..b275480a6fc68347113837514bdd6ee58374f7f8 100644 (file)
@@ -660,6 +660,9 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
         "windows" | "unix" => ret.push(attr::mk_word_item(fam)),
         _ => (),
     }
+    if sess.target.target.options.has_elf_tls {
+        ret.push(attr::mk_word_item(InternedString::new("target_thread_local")));
+    }
     if sess.opts.debug_assertions {
         ret.push(attr::mk_word_item(InternedString::new("debug_assertions")));
     }
index 51abab6609a86c52997e73b576723a21a4204833..21bfd87e412dd5d899ed8ad226d5b0b852d3fa2c 100644 (file)
@@ -11,7 +11,8 @@
 use target::Target;
 
 pub fn target() -> Target {
-    let base = super::linux_base::opts();
+    let mut base = super::linux_base::opts();
+    base.has_elf_tls = false;
     Target {
         llvm_target: "aarch64-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
index 8b75bb3941477b356aef4df75b75e253961f5614..ffcb6f971ae25ce793273f21e7a714414e777f1e 100644 (file)
@@ -8,10 +8,30 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::env;
+
 use target::TargetOptions;
-use std::default::Default;
 
 pub fn opts() -> TargetOptions {
+    // ELF TLS is only available in OSX 10.7+. If you try to compile for 10.6
+    // either the linker will complain if it is used or the binary will end up
+    // segfaulting at runtime when run on 10.6. Rust by default supports OSX
+    // 10.7+, but there is a standard environment variable,
+    // MACOSX_DEPLOYMENT_TARGET, which is used to signal targeting older
+    // versions of OSX. For example compiling on 10.10 with
+    // MACOSX_DEPLOYMENT_TARGET set to 10.6 will cause the linker to generate
+    // warnings about the usage of ELF TLS.
+    //
+    // Here we detect what version is being requested, defaulting to 10.7. ELF
+    // TLS is flagged as enabled if it looks to be supported.
+    let deployment_target = env::var("MACOSX_DEPLOYMENT_TARGET").ok();
+    let version = deployment_target.as_ref().and_then(|s| {
+        let mut i = s.splitn(2, ".");
+        i.next().and_then(|a| i.next().map(|b| (a, b)))
+    }).and_then(|(a, b)| {
+        a.parse::<u32>().and_then(|a| b.parse::<u32>().map(|b| (a, b))).ok()
+    }).unwrap_or((10, 7));
+
     TargetOptions {
         // OSX has -dead_strip, which doesn't rely on ffunction_sections
         function_sections: false,
@@ -25,6 +45,7 @@ pub fn opts() -> TargetOptions {
         archive_format: "bsd".to_string(),
         pre_link_args: Vec::new(),
         exe_allocation_crate: super::maybe_jemalloc(),
+        has_elf_tls: version >= (10, 7),
         .. Default::default()
     }
 }
index 77030f5d76827f929c5d8cd1ea22b533386fa20c..d182fd9605640677322f9d1d425a6732d6bdb488 100644 (file)
@@ -88,6 +88,7 @@ pub fn opts(arch: Arch) -> TargetOptions {
         dynamic_linking: false,
         executables: true,
         pre_link_args: pre_link_args(arch),
+        has_elf_tls: false,
         .. super::apple_base::opts()
     }
 }
index 732f1a353a8bd719c1f363e5fec3c02c9837765d..7776aaacd00b1b8f2f2506265a79674658be9917 100644 (file)
@@ -13,6 +13,7 @@
 pub fn target() -> Target {
     let mut base = super::android_base::opts();
     base.features = "+v7".to_string();
+    base.has_elf_tls = false;
 
     Target {
         llvm_target: "arm-linux-androideabi".to_string(),
index 6492fa5015970e07ca149a11c3ab32866dadf997..0efcf73ee86808ecff5243e64d199410ffc996a1 100644 (file)
@@ -30,6 +30,7 @@ pub fn opts() -> TargetOptions {
         position_independent_executables: true,
         archive_format: "gnu".to_string(),
         exe_allocation_crate: super::maybe_jemalloc(),
+        has_elf_tls: true,
         .. Default::default()
     }
 }
index f259698a220e2be8022a92de7bc1fae45b0b3be7..666903b4eed42a881dc1422cce04075b16d85f64 100644 (file)
@@ -195,6 +195,10 @@ pub struct TargetOptions {
     /// Default crate for allocation symbols to link against
     pub lib_allocation_crate: String,
     pub exe_allocation_crate: String,
+
+    /// Flag indicating whether ELF TLS (e.g. #[thread_local]) is available for
+    /// this target.
+    pub has_elf_tls: bool,
 }
 
 impl Default for TargetOptions {
@@ -240,6 +244,7 @@ fn default() -> TargetOptions {
             lib_allocation_crate: "alloc_system".to_string(),
             exe_allocation_crate: "alloc_system".to_string(),
             allow_asm: true,
+            has_elf_tls: false,
         }
     }
 }
index 5f2548a550467c6e77fe4636aed92bac369375e9..89299c01199756ca5e7c6578f1806e6ee7b5d56e 100644 (file)
@@ -606,7 +606,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         feature_gated_cfgs.sort();
         feature_gated_cfgs.dedup();
         for cfg in &feature_gated_cfgs {
-            cfg.check_and_emit(sess.diagnostic(), &features);
+            cfg.check_and_emit(sess.diagnostic(), &features, sess.codemap());
         }
     });
 
index cc158eba3c2896360dfa0ff981720390282733ee..e66cc49290adf86cc0a28bd08e0092b6bdc215bf 100644 (file)
 #![feature(borrow_state)]
 #![feature(box_syntax)]
 #![feature(cfg_target_vendor)]
+#![feature(cfg_target_thread_local)]
 #![feature(char_internals)]
 #![feature(clone_from_slice)]
 #![feature(collections)]
index 8383b3ec18972e0e0d3296cd542dff1ad352c940..9b1046f39a7b34d8ee5de98c2dcb681248bfec38 100644 (file)
 //! the standard library This varies per-platform, but these libraries are
 //! necessary for running libstd.
 
-// A few small shims in C that haven't been translated to Rust yet
-#[cfg(all(not(test), not(windows)))]
-#[link(name = "rust_builtin", kind = "static")]
-extern {}
-
 // LLVM implements the `frem` instruction as a call to `fmod`, which lives in
 // libm. Hence, we must explicitly link to it.
 //
index e634c10d8b7dc64aac46b960a8679c11bc3d801e..e8575a6c21cf13c0eb159766123a3c415df28c05 100644 (file)
@@ -14,7 +14,8 @@
 use ffi::{CString, CStr, OsString, OsStr};
 use fmt;
 use io::{self, Error, ErrorKind, SeekFrom};
-use libc::{self, c_int, off_t, c_char, mode_t};
+use libc::{dirent, readdir_r};
+use libc::{self, c_int, off_t, mode_t};
 use mem;
 use path::{Path, PathBuf};
 use ptr;
@@ -43,7 +44,7 @@ unsafe impl Send for Dir {}
 unsafe impl Sync for Dir {}
 
 pub struct DirEntry {
-    buf: Vec<u8>, // actually *mut libc::dirent
+    entry: dirent,
     root: Arc<PathBuf>,
 }
 
@@ -126,32 +127,22 @@ impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        extern {
-            fn rust_dirent_t_size() -> libc::size_t;
-        }
-
-        let mut buf: Vec<u8> = Vec::with_capacity(unsafe {
-            rust_dirent_t_size()
-        });
-        let ptr = buf.as_mut_ptr() as *mut libc::dirent;
-
-        let mut entry_ptr = ptr::null_mut();
-        loop {
-            if unsafe { libc::readdir_r(self.dirp.0, ptr, &mut entry_ptr) != 0 } {
-                return Some(Err(Error::last_os_error()))
-            }
-            if entry_ptr.is_null() {
-                return None
-            }
-
-            let entry = DirEntry {
-                buf: buf,
+        unsafe {
+            let mut ret = DirEntry {
+                entry: mem::zeroed(),
                 root: self.root.clone()
             };
-            if entry.name_bytes() == b"." || entry.name_bytes() == b".." {
-                buf = entry.buf;
-            } else {
-                return Some(Ok(entry))
+            let mut entry_ptr = ptr::null_mut();
+            loop {
+                if readdir_r(self.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
+                    return Some(Err(Error::last_os_error()))
+                }
+                if entry_ptr.is_null() {
+                    return None
+                }
+                if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
+                    return Some(Ok(ret))
+                }
             }
         }
     }
@@ -166,7 +157,7 @@ fn drop(&mut self) {
 
 impl DirEntry {
     pub fn path(&self) -> PathBuf {
-        self.root.join(<OsStr as OsStrExt>::from_bytes(self.name_bytes()))
+        self.root.join(OsStr::from_bytes(self.name_bytes()))
     }
 
     pub fn file_name(&self) -> OsString {
@@ -178,35 +169,64 @@ pub fn metadata(&self) -> io::Result<FileAttr> {
     }
 
     pub fn file_type(&self) -> io::Result<FileType> {
-        extern {
-            fn rust_dir_get_mode(ptr: *mut libc::dirent) -> c_int;
-        }
-        unsafe {
-            match rust_dir_get_mode(self.dirent()) {
-                -1 => lstat(&self.path()).map(|m| m.file_type()),
-                n => Ok(FileType { mode: n as mode_t }),
-            }
+        match self.entry.d_type {
+            libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
+            libc::DT_FIFO => Ok(FileType { mode: libc::S_IFIFO }),
+            libc::DT_LNK => Ok(FileType { mode: libc::S_IFLNK }),
+            libc::DT_REG => Ok(FileType { mode: libc::S_IFREG }),
+            libc::DT_SOCK => Ok(FileType { mode: libc::S_IFSOCK }),
+            libc::DT_DIR => Ok(FileType { mode: libc::S_IFDIR }),
+            libc::DT_BLK => Ok(FileType { mode: libc::S_IFBLK }),
+            _ => lstat(&self.path()).map(|m| m.file_type()),
         }
     }
 
+    #[cfg(any(target_os = "macos",
+              target_os = "ios",
+              target_os = "linux"))]
     pub fn ino(&self) -> raw::ino_t {
-        extern {
-            fn rust_dir_get_ino(ptr: *mut libc::dirent) -> raw::ino_t;
-        }
-        unsafe { rust_dir_get_ino(self.dirent()) }
+        self.entry.d_ino
+    }
+
+    #[cfg(target_os = "android")]
+    pub fn ino(&self) -> raw::ino_t {
+        self.entry.d_ino as raw::ino_t
+    }
+
+    #[cfg(any(target_os = "freebsd",
+              target_os = "openbsd",
+              target_os = "bitrig",
+              target_os = "netbsd",
+              target_os = "dragonfly"))]
+    pub fn ino(&self) -> raw::ino_t {
+        self.entry.d_fileno
     }
 
+    #[cfg(any(target_os = "macos",
+              target_os = "ios",
+              target_os = "netbsd"))]
     fn name_bytes(&self) -> &[u8] {
-        extern {
-            fn rust_list_dir_val(ptr: *mut libc::dirent) -> *const c_char;
+        unsafe {
+            ::slice::from_raw_parts(self.entry.d_name.as_ptr() as *const u8,
+                                    self.entry.d_namlen as usize)
         }
+    }
+    #[cfg(any(target_os = "freebsd",
+              target_os = "dragonfly",
+              target_os = "bitrig",
+              target_os = "openbsd"))]
+    fn name_bytes(&self) -> &[u8] {
         unsafe {
-            CStr::from_ptr(rust_list_dir_val(self.dirent())).to_bytes()
+            ::slice::from_raw_parts(self.entry.d_name.as_ptr() as *const u8,
+                                    self.entry.d_namelen as usize)
         }
     }
-
-    fn dirent(&self) -> *mut libc::dirent {
-        self.buf.as_ptr() as *mut _
+    #[cfg(any(target_os = "android",
+              target_os = "linux"))]
+    fn name_bytes(&self) -> &[u8] {
+        unsafe {
+            CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
+        }
     }
 }
 
index 12b9d6191a05fb5bd483528ba2397d29d11c8c83..c62960d74cb1ca290c4b1e74621a1cc93901457f 100644 (file)
 /// Returns the platform-specific value of errno
 pub fn errno() -> i32 {
     extern {
-        #[cfg_attr(any(target_os = "linux", target_os = "android"), link_name = "__errno_location")]
-        #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd",
+        #[cfg_attr(any(target_os = "linux"), link_name = "__errno_location")]
+        #[cfg_attr(any(target_os = "bitrig",
+                       target_os = "netbsd",
+                       target_os = "openbsd",
+                       target_os = "android",
                        target_env = "newlib"),
                    link_name = "__errno")]
         #[cfg_attr(target_os = "dragonfly", link_name = "__dfly_error")]
-        #[cfg_attr(any(target_os = "macos", target_os = "ios", target_os = "freebsd"),
+        #[cfg_attr(any(target_os = "macos",
+                       target_os = "ios",
+                       target_os = "freebsd"),
                    link_name = "__error")]
         fn errno_location() -> *const c_int;
     }
@@ -173,17 +178,19 @@ pub fn current_exe() -> io::Result<PathBuf> {
                        libc::KERN_PROC_PATHNAME as c_int,
                        -1 as c_int];
         let mut sz: libc::size_t = 0;
-        let err = libc::sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
-                               ptr::null_mut(), &mut sz, ptr::null_mut(),
-                               0 as libc::size_t);
-        if err != 0 { return Err(io::Error::last_os_error()); }
-        if sz == 0 { return Err(io::Error::last_os_error()); }
+        try!(cvt(libc::sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
+                              ptr::null_mut(), &mut sz, ptr::null_mut(),
+                              0 as libc::size_t)));
+        if sz == 0 {
+            return Err(io::Error::last_os_error())
+        }
         let mut v: Vec<u8> = Vec::with_capacity(sz as usize);
-        let err = libc::sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
-                               v.as_mut_ptr() as *mut libc::c_void, &mut sz,
-                               ptr::null_mut(), 0 as libc::size_t);
-        if err != 0 { return Err(io::Error::last_os_error()); }
-        if sz == 0 { return Err(io::Error::last_os_error()); }
+        try!(cvt(libc::sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
+                              v.as_mut_ptr() as *mut libc::c_void, &mut sz,
+                              ptr::null_mut(), 0 as libc::size_t)));
+        if sz == 0 {
+            return Err(io::Error::last_os_error());
+        }
         v.set_len(sz as usize - 1); // chop off trailing NUL
         Ok(PathBuf::from(OsString::from_vec(v)))
     }
@@ -201,22 +208,28 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
 pub fn current_exe() -> io::Result<PathBuf> {
-    use sync::StaticMutex;
-    static LOCK: StaticMutex = StaticMutex::new();
-
-    extern {
-        fn rust_current_exe() -> *const c_char;
-    }
-
-    let _guard = LOCK.lock();
-
     unsafe {
-        let v = rust_current_exe();
-        if v.is_null() {
-            Err(io::Error::last_os_error())
+        let mut mib = [libc::CTL_KERN,
+                       libc::KERN_PROC_ARGS,
+                       libc::getpid(),
+                       libc::KERN_PROC_ARGV];
+        let mib = mib.as_mut_ptr();
+        let mut argv_len = 0;
+        try!(cvt(libc::sysctl(mib, 4, 0 as *mut _, &mut argv_len,
+                              0 as *mut _, 0)));
+        let mut argv = Vec::<*const libc::c_char>::with_capacity(argv_len as usize);
+        try!(cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _,
+                              &mut argv_len, 0 as *mut _, 0)));
+        argv.set_len(argv_len as usize);
+        if argv[0].is_null() {
+            return Err(io::Error::new(io::ErrorKind::Other,
+                                      "no current exe available"))
+        }
+        let argv0 = CStr::from_ptr(argv[0]).to_bytes();
+        if argv0[0] == b'.' || argv0.iter().any(|b| *b == b'/') {
+            ::fs::canonicalize(OsStr::from_bytes(argv0))
         } else {
-            let vec = CStr::from_ptr(v).to_bytes().to_vec();
-            Ok(PathBuf::from(OsString::from_vec(vec)))
+            Ok(PathBuf::from(OsStr::from_bytes(argv0)))
         }
     }
 }
index 870247f7e82fc722c30bcff15fbecc1163f64643..ca0f10315625304313699bbf75ca67268cf68965 100644 (file)
 use cell::UnsafeCell;
 use mem;
 
-// Sure wish we had macro hygiene, no?
-#[doc(hidden)]
-pub use self::imp::Key as __KeyInner;
-
 /// A thread local storage key which owns its contents.
 ///
 /// This key uses the fastest possible implementation available to it for the
 /// });
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct LocalKey<T:'static> {
-    // The key itself may be tagged with #[thread_local], and this `Key` is
-    // stored as a `static`, and it's not valid for a static to reference the
-    // address of another thread_local static. For this reason we kinda wonkily
-    // work around this by generating a shim function which will give us the
-    // address of the inner TLS key at runtime.
+pub struct LocalKey<T: 'static> {
+    // This outer `LocalKey<T>` type is what's going to be stored in statics,
+    // but actual data inside will sometimes be tagged with #[thread_local].
+    // It's not valid for a true static to reference a #[thread_local] static,
+    // so we get around that by exposing an accessor through a layer of function
+    // indirection (this thunk).
+    //
+    // Note that the thunk is itself unsafe because the returned lifetime of the
+    // slot where data lives, `'static`, is not actually valid. The lifetime
+    // here is actually `'thread`!
     //
-    // This is trivially devirtualizable by LLVM because we never store anything
-    // to this field and rustc can declare the `static` as constant as well.
-    inner: fn() -> &'static __KeyInner<T>,
+    // Although this is an extra layer of indirection, it should in theory be
+    // trivially devirtualizable by LLVM because the value of `inner` never
+    // changes and the constant should be readonly within a crate. This mainly
+    // only runs into problems when TLS statics are exported across crates.
+    inner: unsafe fn() -> Option<&'static UnsafeCell<Option<T>>>,
 
     // initialization routine to invoke to create a value
     init: fn() -> T,
 }
 
-// Macro pain #4586:
-//
-// When cross compiling, rustc will load plugins and macros from the *host*
-// platform before search for macros from the target platform. This is primarily
-// done to detect, for example, plugins. Ideally the macro below would be
-// defined once per module below, but unfortunately this means we have the
-// following situation:
-//
-// 1. We compile libstd for x86_64-unknown-linux-gnu, this thread_local!() macro
-//    will inject #[thread_local] statics.
-// 2. We then try to compile a program for arm-linux-androideabi
-// 3. The compiler has a host of linux and a target of android, so it loads
-//    macros from the *linux* libstd.
-// 4. The macro generates a #[thread_local] field, but the android libstd does
-//    not use #[thread_local]
-// 5. Compile error about structs with wrong fields.
-//
-// To get around this, we're forced to inject the #[cfg] logic into the macro
-// itself. Woohoo.
-
 /// Declare a new thread local storage key of type `std::thread::LocalKey`.
 ///
 /// See [LocalKey documentation](thread/struct.LocalKey.html) for more
@@ -103,36 +85,14 @@ pub struct LocalKey<T:'static> {
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable]
-#[cfg(not(no_elf_tls))]
-macro_rules! thread_local {
-    (static $name:ident: $t:ty = $init:expr) => (
-        static $name: $crate::thread::LocalKey<$t> =
-            __thread_local_inner!($t, $init,
-                #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
-                               not(target_arch = "aarch64")),
-                           thread_local)]);
-    );
-    (pub static $name:ident: $t:ty = $init:expr) => (
-        pub static $name: $crate::thread::LocalKey<$t> =
-            __thread_local_inner!($t, $init,
-                #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
-                               not(target_arch = "aarch64")),
-                           thread_local)]);
-    );
-}
-
-#[macro_export]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow_internal_unstable]
-#[cfg(no_elf_tls)]
 macro_rules! thread_local {
     (static $name:ident: $t:ty = $init:expr) => (
         static $name: $crate::thread::LocalKey<$t> =
-            __thread_local_inner!($t, $init, #[]);
+            __thread_local_inner!($t, $init);
     );
     (pub static $name:ident: $t:ty = $init:expr) => (
         pub static $name: $crate::thread::LocalKey<$t> =
-            __thread_local_inner!($t, $init, #[]);
+            __thread_local_inner!($t, $init);
     );
 }
 
@@ -143,12 +103,25 @@ macro_rules! thread_local {
 #[macro_export]
 #[allow_internal_unstable]
 macro_rules! __thread_local_inner {
-    ($t:ty, $init:expr, #[$($attr:meta),*]) => {{
-        $(#[$attr])*
-        static __KEY: $crate::thread::__LocalKeyInner<$t> =
-            $crate::thread::__LocalKeyInner::new();
+    ($t:ty, $init:expr) => {{
         fn __init() -> $t { $init }
-        fn __getit() -> &'static $crate::thread::__LocalKeyInner<$t> { &__KEY }
+
+        unsafe fn __getit() -> $crate::option::Option<
+            &'static $crate::cell::UnsafeCell<
+                $crate::option::Option<$t>>>
+        {
+            #[thread_local]
+            #[cfg(target_thread_local)]
+            static __KEY: $crate::thread::__ElfLocalKeyInner<$t> =
+                $crate::thread::__ElfLocalKeyInner::new();
+
+            #[cfg(not(target_thread_local))]
+            static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
+                $crate::thread::__OsLocalKeyInner::new();
+
+            __KEY.get()
+        }
+
         $crate::thread::LocalKey::new(__getit, __init)
     }}
 }
@@ -190,11 +163,11 @@ impl<T: 'static> LocalKey<T> {
     #[unstable(feature = "thread_local_internals",
                reason = "recently added to create a key",
                issue = "0")]
-    pub const fn new(inner: fn() -> &'static __KeyInner<T>,
+    pub const fn new(inner: unsafe fn() -> Option<&'static UnsafeCell<Option<T>>>,
                      init: fn() -> T) -> LocalKey<T> {
         LocalKey {
             inner: inner,
-            init: init
+            init: init,
         }
     }
 
@@ -211,10 +184,10 @@ pub const fn new(inner: fn() -> &'static __KeyInner<T>,
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with<F, R>(&'static self, f: F) -> R
                       where F: FnOnce(&T) -> R {
-        let slot = (self.inner)();
         unsafe {
-            let slot = slot.get().expect("cannot access a TLS value during or \
-                                          after it is destroyed");
+            let slot = (self.inner)();
+            let slot = slot.expect("cannot access a TLS value during or \
+                                    after it is destroyed");
             f(match *slot.get() {
                 Some(ref inner) => inner,
                 None => self.init(slot),
@@ -270,7 +243,7 @@ unsafe fn init(&self, slot: &UnsafeCell<Option<T>>) -> &T {
                issue = "27716")]
     pub fn state(&'static self) -> LocalKeyState {
         unsafe {
-            match (self.inner)().get() {
+            match (self.inner)() {
                 Some(cell) => {
                     match *cell.get() {
                         Some(..) => LocalKeyState::Valid,
@@ -283,11 +256,9 @@ pub fn state(&'static self) -> LocalKeyState {
     }
 }
 
-#[cfg(all(any(target_os = "macos", target_os = "linux"),
-          not(target_arch = "aarch64"),
-          not(no_elf_tls)))]
+#[cfg(target_thread_local)]
 #[doc(hidden)]
-mod imp {
+pub mod elf {
     use cell::{Cell, UnsafeCell};
     use intrinsics;
     use ptr;
@@ -431,11 +402,8 @@ fn _tlv_atexit(dtor: unsafe extern fn(*mut u8),
     }
 }
 
-#[cfg(any(not(any(target_os = "macos", target_os = "linux")),
-          target_arch = "aarch64",
-          no_elf_tls))]
 #[doc(hidden)]
-mod imp {
+pub mod os {
     use prelude::v1::*;
 
     use cell::{Cell, UnsafeCell};
index d4f04d5d94f1fa8cde373c471fb3ce60bac88d75..0e525f394216c9bdadef5d415f8e40e54fd16a9b 100644 (file)
 pub use self::scoped_tls::ScopedKey;
 
 #[unstable(feature = "libstd_thread_internals", issue = "0")]
-#[doc(hidden)] pub use self::local::__KeyInner as __LocalKeyInner;
+#[cfg(target_thread_local)]
+#[doc(hidden)] pub use self::local::elf::Key as __ElfLocalKeyInner;
+#[unstable(feature = "libstd_thread_internals", issue = "0")]
+#[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner;
 #[unstable(feature = "libstd_thread_internals", issue = "0")]
 #[doc(hidden)] pub use self::scoped_tls::__KeyInner as __ScopedKeyInner;
 
index b2989c42a9e9291827ec1ce85810f81770074485..4ea0fd76fea4a6c38868651b0a34eb188f4aa4ae 100644 (file)
 
     // allow using type ascription in expressions
     ("type_ascription", "1.6.0", Some(23416), Active),
+
+    // Allows cfg(target_thread_local)
+    ("cfg_target_thread_local", "1.7.0", Some(29594), Active),
 ];
 // (changing above list without updating src/doc/reference.md makes @cmr sad)
 
@@ -414,6 +417,8 @@ fn f($x: &Features) -> bool {
     // (name in cfg, feature, function to check if the feature is enabled)
     ("target_feature", "cfg_target_feature", cfg_fn!(|x| x.cfg_target_feature)),
     ("target_vendor", "cfg_target_vendor", cfg_fn!(|x| x.cfg_target_vendor)),
+    ("target_thread_local", "cfg_target_thread_local",
+     cfg_fn!(|x| x.cfg_target_thread_local)),
 ];
 
 #[derive(Debug, Eq, PartialEq)]
@@ -449,10 +454,13 @@ fn partial_cmp(&self, other: &GatedCfgAttr) -> Option<cmp::Ordering> {
 }
 
 impl GatedCfgAttr {
-    pub fn check_and_emit(&self, diagnostic: &Handler, features: &Features) {
+    pub fn check_and_emit(&self,
+                          diagnostic: &Handler,
+                          features: &Features,
+                          codemap: &CodeMap) {
         match *self {
             GatedCfgAttr::GatedCfg(ref cfg) => {
-                cfg.check_and_emit(diagnostic, features);
+                cfg.check_and_emit(diagnostic, features, codemap);
             }
             GatedCfgAttr::GatedAttr(span) => {
                 if !features.stmt_expr_attributes {
@@ -479,9 +487,12 @@ pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
                       }
                   })
     }
-    fn check_and_emit(&self, diagnostic: &Handler, features: &Features) {
+    fn check_and_emit(&self,
+                      diagnostic: &Handler,
+                      features: &Features,
+                      codemap: &CodeMap) {
         let (cfg, feature, has_feature) = GATED_CFGS[self.index];
-        if !has_feature(features) {
+        if !has_feature(features) && !codemap.span_allows_unstable(self.span) {
             let explain = format!("`cfg({})` is experimental and subject to change", cfg);
             emit_feature_err(diagnostic, feature, self.span, GateIssue::Language, &explain);
         }
@@ -541,6 +552,7 @@ pub struct Features {
     pub type_macros: bool,
     pub cfg_target_feature: bool,
     pub cfg_target_vendor: bool,
+    pub cfg_target_thread_local: bool,
     pub augmented_assignments: bool,
     pub braced_empty_structs: bool,
     pub staged_api: bool,
@@ -575,6 +587,7 @@ pub fn new() -> Features {
             type_macros: false,
             cfg_target_feature: false,
             cfg_target_vendor: false,
+            cfg_target_thread_local: false,
             augmented_assignments: false,
             braced_empty_structs: false,
             staged_api: false,
@@ -1157,6 +1170,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &Handler,
         type_macros: cx.has_feature("type_macros"),
         cfg_target_feature: cx.has_feature("cfg_target_feature"),
         cfg_target_vendor: cx.has_feature("cfg_target_vendor"),
+        cfg_target_thread_local: cx.has_feature("cfg_target_thread_local"),
         augmented_assignments: cx.has_feature("augmented_assignments"),
         braced_empty_structs: cx.has_feature("braced_empty_structs"),
         staged_api: cx.has_feature("staged_api"),
index 20d7c66cf12217789cb784875a9dc8d0d8b33c95..a844bdf1351d9041892c38bd15777caf7becce72 100644 (file)
@@ -906,10 +906,45 @@ struct SYSTEM_INFO {
         }
     }
 
-    #[cfg(unix)]
+    #[cfg(any(target_os = "linux",
+              target_os = "macos",
+              target_os = "ios",
+              target_os = "android"))]
     fn num_cpus() -> usize {
-        extern { fn rust_get_num_cpus() -> libc::uintptr_t; }
-        unsafe { rust_get_num_cpus() as usize }
+        unsafe {
+            libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize
+        }
+    }
+
+    #[cfg(any(target_os = "freebsd",
+              target_os = "dragonfly",
+              target_os = "bitrig",
+              target_os = "openbsd",
+              target_os = "netbsd"))]
+    fn num_cpus() -> usize {
+        let mut cpus: libc::c_uint = 0;
+        let mut CPUS_SIZE = std::mem::size_of_val(&cpus);
+        let mut mib = [libc::CTL_HW, libc::HW_AVAILCPU, 0, 0];
+
+        unsafe {
+            libc::sysctl(mib.as_mut_ptr(), 2,
+                         &mut cpus as *mut _ as *mut _,
+                         &mut CPUS_SIZE as *mut _ as *mut _,
+                         0 as *mut _, 0);
+        }
+        if cpus < 1 {
+            mib[1] = HW_NCPU;
+            unsafe {
+                libc::sysctl(mib.as_mut_ptr(), 2,
+                             &mut cpus as *mut _ as *mut _,
+                             &mut CPUS_SIZE as *mut _ as *mut _,
+                             0 as *mut _, 0);
+            }
+            if cpus < 1 {
+                cpus = 1;
+            }
+        }
+        cpus as usize
     }
 }
 
diff --git a/src/rt/rust_android_dummy.c b/src/rt/rust_android_dummy.c
deleted file mode 100644 (file)
index c322dc6..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifdef __ANDROID__
-
-#include "rust_android_dummy.h"
-#include <math.h>
-#include <errno.h>
-
-int backtrace(void **array, int size) { return 0; }
-
-char **backtrace_symbols(void *const *array, int size) { return 0; }
-
-void backtrace_symbols_fd (void *const *array, int size, int fd) {}
-
-volatile int* __errno_location() {
-    return &errno;
-}
-
-float log2f(float f)
-{
-    return logf( f ) / logf( 2 );
-}
-
-double log2( double n )
-{
-    return log( n ) / log( 2 );
-}
-
-double exp10( double x )
-{
-    return pow( 10, x );
-}
-
-void telldir()
-{
-}
-
-void seekdir()
-{
-}
-
-void mkfifo()
-{
-}
-
-void abs()
-{
-}
-
-void labs()
-{
-}
-
-void rand()
-{
-}
-
-void srand()
-{
-}
-
-void atof()
-{
-}
-
-int glob(const char *pattern,
-                    int flags,
-                    int (*errfunc) (const char *epath, int eerrno),
-                    glob_t *pglob)
-{
-    return 0;
-}
-
-void globfree(glob_t *pglob)
-{
-}
-
-int pthread_atfork(void (*prefork)(void),
-                              void (*postfork_parent)(void),
-                              void (*postfork_child)(void))
-{
-    return 0;
-}
-
-int mlockall(int flags)
-{
-    return 0;
-}
-
-int munlockall(void)
-{
-    return 0;
-}
-
-int shm_open(const char *name, int oflag, mode_t mode)
-{
-    return 0;
-}
-
-int shm_unlink(const char *name)
-{
-    return 0;
-}
-
-int posix_madvise(void *addr, size_t len, int advice)
-{
-    return 0;
-}
-
-#endif
diff --git a/src/rt/rust_builtin.c b/src/rt/rust_builtin.c
deleted file mode 100644 (file)
index c2168d7..0000000
+++ /dev/null
@@ -1,470 +0,0 @@
-// Copyright 2012-2015 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.
-
-#if !defined(_WIN32)
-
-#include <stdint.h>
-#include <time.h>
-#include <string.h>
-#include <assert.h>
-#include <stdlib.h>
-
-
-#include <dirent.h>
-#include <pthread.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#ifdef __APPLE__
-#include <TargetConditionals.h>
-#include <mach/mach_time.h>
-
-#if !(TARGET_OS_IPHONE)
-#include <crt_externs.h>
-#endif
-#endif
-
-char*
-rust_list_dir_val(struct dirent* entry_ptr) {
-    return entry_ptr->d_name;
-}
-
-// Android's struct dirent does have d_type from the very beginning
-// (android-3). _DIRENT_HAVE_D_TYPE is not defined all the way to android-21
-// though...
-#if defined(__ANDROID__)
-# define _DIRENT_HAVE_D_TYPE
-#endif
-
-int
-rust_dir_get_mode(struct dirent* entry_ptr) {
-#if defined(_DIRENT_HAVE_D_TYPE) || defined(__APPLE__)
-    switch (entry_ptr->d_type) {
-        case DT_BLK: return S_IFBLK;
-        case DT_CHR: return S_IFCHR;
-        case DT_FIFO: return S_IFIFO;
-        case DT_LNK: return S_IFLNK;
-        case DT_REG: return S_IFREG;
-        case DT_SOCK: return S_IFSOCK;
-        case DT_DIR: return S_IFDIR;
-    }
-#endif
-    return -1;
-}
-
-ino_t
-rust_dir_get_ino(struct dirent* entry_ptr) {
-    return entry_ptr->d_ino;
-}
-
-DIR*
-rust_opendir(char *dirname) {
-    return opendir(dirname);
-}
-
-int
-rust_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
-    return readdir_r(dirp, entry, result);
-}
-
-size_t
-rust_dirent_t_size() {
-    return sizeof(struct dirent);
-}
-
-#if defined(__BSD__)
-static int
-get_num_cpus() {
-    /* swiped from http://stackoverflow.com/questions/150355/
-       programmatically-find-the-number-of-cores-on-a-machine */
-
-    unsigned int numCPU;
-    int mib[4];
-    size_t len = sizeof(numCPU);
-
-    /* set the mib for hw.ncpu */
-    mib[0] = CTL_HW;
-    mib[1] = HW_AVAILCPU;  // alternatively, try HW_NCPU;
-
-    /* get the number of CPUs from the system */
-    sysctl(mib, 2, &numCPU, &len, NULL, 0);
-
-    if( numCPU < 1 ) {
-        mib[1] = HW_NCPU;
-        sysctl( mib, 2, &numCPU, &len, NULL, 0 );
-
-        if( numCPU < 1 ) {
-            numCPU = 1;
-        }
-    }
-    return numCPU;
-}
-#elif defined(__GNUC__)
-static int
-get_num_cpus() {
-    return sysconf(_SC_NPROCESSORS_ONLN);
-}
-#endif
-
-uintptr_t
-rust_get_num_cpus() {
-    return get_num_cpus();
-}
-
-#if defined(__DragonFly__)
-#include <errno.h>
-// In DragonFly __error() is an inline function and as such
-// no symbol exists for it.
-int *__dfly_error(void) { return __error(); }
-#endif
-
-#if defined(__Bitrig__)
-#include <stdio.h>
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <limits.h>
-
-int rust_get_path(void *p, size_t* sz)
-{
-  int mib[4];
-  char *eq = NULL;
-  char *key = NULL;
-  char *val = NULL;
-  char **menv = NULL;
-  size_t maxlen, len;
-  int nenv = 0;
-  int i;
-
-  if ((p == NULL) && (sz == NULL))
-    return -1;
-
-  /* get the argv array */
-  mib[0] = CTL_KERN;
-  mib[1] = KERN_PROC_ARGS;
-  mib[2] = getpid();
-  mib[3] = KERN_PROC_ENV;
-
-  /* get the number of bytes needed to get the env */
-  maxlen = 0;
-  if (sysctl(mib, 4, NULL, &maxlen, NULL, 0) == -1)
-    return -1;
-
-  /* allocate the buffer */
-  if ((menv = calloc(maxlen, sizeof(char))) == NULL)
-    return -1;
-
-  /* get the env array */
-  if (sysctl(mib, 4, menv, &maxlen, NULL, 0) == -1)
-  {
-    free(menv);
-    return -1;
-  }
-
-  mib[3] = KERN_PROC_NENV;
-  len = sizeof(int);
-  /* get the length of env array */
-  if (sysctl(mib, 4, &nenv, &len, NULL, 0) == -1)
-  {
-    free(menv);
-    return -1;
-  }
-
-  /* find _ key and resolve the value */
-  for (i = 0; i < nenv; i++)
-  {
-    if ((eq = strstr(menv[i], "=")) == NULL)
-      continue;
-
-    key = menv[i];
-    val = eq + 1;
-    *eq = '\0';
-
-    if (strncmp(key, "PATH", maxlen) != 0)
-      continue;
-
-    if (p == NULL)
-    {
-      /* return the length of the value + NUL */
-      *sz = strnlen(val, maxlen) + 1;
-      free(menv);
-      return 0;
-    }
-    else
-    {
-      /* copy *sz bytes to the output buffer */
-      memcpy(p, val, *sz);
-      free(menv);
-      return 0;
-    }
-  }
-
-  free(menv);
-  return -1;
-}
-
-int rust_get_path_array(void * p, size_t * sz)
-{
-  char *path, *str;
-  char **buf;
-  int i, num;
-  size_t len;
-
-  if ((p == NULL) && (sz == NULL))
-    return -1;
-
-  /* get the length of the PATH value */
-  if (rust_get_path(NULL, &len) == -1)
-    return -1;
-
-  if (len == 0)
-    return -1;
-
-  /* allocate the buffer */
-  if ((path = calloc(len, sizeof(char))) == NULL)
-    return -1;
-
-  /* get the PATH value */
-  if (rust_get_path(path, &len) == -1)
-  {
-    free(path);
-    return -1;
-  }
-
-  /* count the number of parts in the PATH */
-  num = 1;
-  for(str = path; *str != '\0'; str++)
-  {
-    if (*str == ':')
-      num++;
-  }
-
-  /* calculate the size of the buffer for the 2D array */
-  len = (num * sizeof(char*) + 1) + strlen(path) + 1;
-
-  if (p == NULL)
-  {
-    free(path);
-    *sz = len;
-    return 0;
-  }
-
-  /* make sure we have enough buffer space */
-  if (*sz < len)
-  {
-    free(path);
-    return -1;
-  }
-
-  /* zero out the buffer */
-  buf = (char**)p;
-  memset(buf, 0, *sz);
-
-  /* copy the data into the right place */
-  str = p + ((num+1) * sizeof(char*));
-  memcpy(str, path, strlen(path));
-
-  /* parse the path into it's parts */
-  for (i = 0; i < num && (buf[i] = strsep(&str, ":")) != NULL; i++) {;}
-  buf[num] = NULL;
-
-  free(path);
-  return 0;
-}
-
-int rust_get_argv_zero(void* p, size_t* sz)
-{
-  int mib[4];
-  char **argv = NULL;
-  size_t len;
-
-  if ((p == NULL) && (sz == NULL))
-    return -1;
-
-  /* get the argv array */
-  mib[0] = CTL_KERN;
-  mib[1] = KERN_PROC_ARGS;
-  mib[2] = getpid();
-  mib[3] = KERN_PROC_ARGV;
-
-  /* request KERN_PROC_ARGV size */
-  len = 0;
-  if (sysctl(mib, 4, NULL, &len, NULL, 0) == -1)
-    return -1;
-
-  /* allocate buffer to receive the values */
-  if ((argv = malloc(len)) == NULL)
-    return -1;
-
-  /* get the argv array */
-  if (sysctl(mib, 4, argv, &len, NULL, 0) == -1)
-  {
-    free(argv);
-    return -1;
-  }
-
-  /* get length of argv[0] */
-  len = strnlen(argv[0], len) + 1;
-
-  if (p == NULL)
-  {
-    *sz = len;
-    free(argv);
-    return 0;
-  }
-
-  if (*sz < len)
-  {
-    free(argv);
-    return -1;
-  }
-
-  memcpy(p, argv[0], len);
-  free(argv);
-  return 0;
-}
-
-const char * rust_current_exe()
-{
-  static char *self = NULL;
-  char *argv0;
-  char **paths;
-  size_t sz;
-  int i;
-  /* If `PATH_MAX` is defined on the platform, `realpath` will truncate the
-   * resolved path up to `PATH_MAX`. While this can make the resolution fail if
-   * the executable is placed in a deep path, the usage of a buffer whose
-   * length depends on `PATH_MAX` is still memory safe. */
-  char buf[2*PATH_MAX], exe[PATH_MAX];
-
-  if (self != NULL)
-    return self;
-
-  if (rust_get_argv_zero(NULL, &sz) == -1)
-    return NULL;
-  if ((argv0 = calloc(sz, sizeof(char))) == NULL)
-    return NULL;
-  if (rust_get_argv_zero(argv0, &sz) == -1)
-  {
-    free(argv0);
-    return NULL;
-  }
-
-  /* if argv0 is a relative or absolute path, resolve it with realpath */
-  if ((*argv0 == '.') || (*argv0 == '/') || (strstr(argv0, "/") != NULL))
-  {
-    self = realpath(argv0, NULL);
-    free(argv0);
-    return self;
-  }
-
-  /* get the path array */
-  if (rust_get_path_array(NULL, &sz) == -1)
-  {
-    free(argv0);
-    return NULL;
-  }
-  if ((paths = calloc(sz, sizeof(char))) == NULL)
-  {
-    free(argv0);
-    return NULL;
-  }
-  if (rust_get_path_array(paths, &sz) == -1)
-  {
-    free(argv0);
-    free(paths);
-    return NULL;
-  }
-
-  for(i = 0; paths[i] != NULL; i++)
-  {
-    snprintf(buf, 2*PATH_MAX, "%s/%s", paths[i], argv0);
-    if (realpath(buf, exe) == NULL)
-      continue;
-
-    if (access(exe, F_OK | X_OK) == -1)
-      continue;
-
-    self = strdup(exe);
-    free(argv0);
-    free(paths);
-    return self;
-  }
-
-  free(argv0);
-  free(paths);
-  return NULL;
-}
-
-#elif defined(__OpenBSD__)
-
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <limits.h>
-
-const char * rust_current_exe() {
-    static char *self = NULL;
-
-    if (self == NULL) {
-        int mib[4];
-        char **argv = NULL;
-        size_t argv_len;
-
-        /* initialize mib */
-        mib[0] = CTL_KERN;
-        mib[1] = KERN_PROC_ARGS;
-        mib[2] = getpid();
-        mib[3] = KERN_PROC_ARGV;
-
-        /* request KERN_PROC_ARGV size */
-        argv_len = 0;
-        if (sysctl(mib, 4, NULL, &argv_len, NULL, 0) == -1)
-            return (NULL);
-
-        /* allocate size */
-        if ((argv = malloc(argv_len)) == NULL)
-            return (NULL);
-
-        /* request KERN_PROC_ARGV */
-        if (sysctl(mib, 4, argv, &argv_len, NULL, 0) == -1) {
-            free(argv);
-            return (NULL);
-        }
-
-        /* get realpath if possible */
-        if ((argv[0] != NULL) && ((*argv[0] == '.') || (*argv[0] == '/')
-                                || (strstr(argv[0], "/") != NULL)))
-
-            self = realpath(argv[0], NULL);
-        else
-            self = NULL;
-
-        /* cleanup */
-        free(argv);
-    }
-
-    return (self);
-}
-
-#endif
-
-#endif // !defined(_WIN32)
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//