]> git.lizzy.rs Git - rust.git/commitdiff
Basic iOS support
authorValerii Hiora <valerii.hiora@gmail.com>
Mon, 5 May 2014 07:07:49 +0000 (10:07 +0300)
committerValerii Hiora <valerii.hiora@gmail.com>
Thu, 12 Jun 2014 18:15:14 +0000 (21:15 +0300)
37 files changed:
src/liblibc/lib.rs
src/libnative/io/c_unix.rs
src/libnative/io/file_unix.rs
src/libnative/io/mod.rs
src/libnative/io/net.rs
src/libnative/io/process.rs
src/libnative/io/timer_unix.rs
src/librustc/back/arm.rs
src/librustc/back/link.rs
src/librustc/back/mips.rs
src/librustc/back/rpath.rs
src/librustc/back/x86.rs
src/librustc/back/x86_64.rs
src/librustc/driver/config.rs
src/librustc/driver/session.rs
src/librustc/metadata/creader.rs
src/librustc/metadata/loader.rs
src/librustc/middle/trans/cabi_x86.rs
src/librustc/middle/trans/cleanup.rs
src/librustc/middle/trans/debuginfo.rs
src/librustdoc/flock.rs
src/librustrt/args.rs
src/librustrt/lib.rs
src/librustrt/libunwind.rs
src/librustrt/local_ptr.rs
src/librustrt/mutex.rs
src/librustrt/stack.rs
src/librustrt/thread.rs
src/librustrt/thread_local_storage.rs
src/librustrt/unwind.rs
src/libstd/dynamic_lib.rs
src/libstd/os.rs
src/libstd/rand/os.rs
src/libstd/rt/backtrace.rs
src/libstd/rtdeps.rs
src/libsyntax/abi.rs
src/libtime/lib.rs

index ff87b7fb0074bb2d0d08aa32d2b24ab743b8e842..9ed0d50a03e8aae811dc9384a4d8ed9d906353a8 100644 (file)
 pub use consts::os::bsd44::{TCP_KEEPIDLE};
 
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 pub use consts::os::bsd44::{TCP_KEEPALIVE};
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 pub use consts::os::extra::{F_FULLFSYNC};
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 pub use types::os::arch::extra::{mach_timebase_info};
 
 
@@ -1286,6 +1289,7 @@ pub struct WSAPROTOCOL_INFO {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     pub mod os {
         pub mod common {
             pub mod posix01 {
@@ -3106,6 +3110,7 @@ pub mod sysconf {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     pub mod os {
         pub mod c95 {
             use types::os::arch::c95::{c_int, c_uint};
@@ -3769,6 +3774,7 @@ pub mod mman {
     #[cfg(target_os = "linux")]
     #[cfg(target_os = "android")]
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     #[cfg(target_os = "freebsd")]
     pub mod posix88 {
         pub mod stat_ {
@@ -3783,6 +3789,7 @@ pub mod stat_ {
                 #[cfg(target_os = "linux")]
                 #[cfg(target_os = "freebsd")]
                 #[cfg(target_os = "android")]
+                #[cfg(target_os = "ios")]
                 pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
 
                 #[cfg(target_os = "macos")]
@@ -3795,6 +3802,7 @@ pub mod stat_ {
                 #[cfg(target_os = "linux")]
                 #[cfg(target_os = "freebsd")]
                 #[cfg(target_os = "android")]
+                #[cfg(target_os = "ios")]
                 pub fn stat(path: *c_char, buf: *mut stat) -> c_int;
 
                 #[cfg(target_os = "macos")]
@@ -3967,6 +3975,7 @@ pub fn shm_open(name: *c_char, oflag: c_int, mode: mode_t)
     #[cfg(target_os = "linux")]
     #[cfg(target_os = "android")]
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     #[cfg(target_os = "freebsd")]
     pub mod posix01 {
         pub mod stat_ {
@@ -3977,6 +3986,7 @@ pub mod stat_ {
                 #[cfg(target_os = "linux")]
                 #[cfg(target_os = "freebsd")]
                 #[cfg(target_os = "android")]
+                #[cfg(target_os = "ios")]
                 pub fn lstat(path: *c_char, buf: *mut stat) -> c_int;
 
                 #[cfg(target_os = "macos")]
@@ -4076,6 +4086,7 @@ pub mod mman {
     #[cfg(target_os = "linux")]
     #[cfg(target_os = "android")]
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     #[cfg(target_os = "freebsd")]
     pub mod posix08 {
         pub mod unistd {
@@ -4156,6 +4167,7 @@ pub fn sendto(socket: SOCKET, buf: *c_void, len: c_int,
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     #[cfg(target_os = "freebsd")]
     pub mod bsd44 {
         use types::common::c95::{c_void};
@@ -4209,6 +4221,7 @@ pub mod bsd44 {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     pub mod extra {
         use types::os::arch::c95::{c_char, c_int};
 
index e6cb5cb76f11e8cab23897f50b5d2b23c9b11e6a..70fd6310070da0e7cbaa19bd6ad4f3852a96b04f 100644 (file)
@@ -20,6 +20,7 @@
 use libc;
 
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
 pub static FIONBIO: libc::c_ulong = 0x8004667e;
 #[cfg(target_os = "linux", not(target_arch = "mips"))]
@@ -29,6 +30,7 @@
 pub static FIONBIO: libc::c_ulong = 0x667e;
 
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
 pub static FIOCLEX: libc::c_ulong = 0x20006601;
 #[cfg(target_os = "linux", not(target_arch = "mips"))]
@@ -38,6 +40,7 @@
 pub static FIOCLEX: libc::c_ulong = 0x6601;
 
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
 pub static MSG_DONTWAIT: libc::c_int = 0x80;
 #[cfg(target_os = "linux")]
@@ -75,6 +78,7 @@ pub fn sigaction(signum: libc::c_int,
 }
 
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 mod select {
     pub static FD_SETSIZE: uint = 1024;
 
@@ -187,6 +191,7 @@ pub struct sigset_t {
 }
 
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
 mod signal {
     use libc;
@@ -201,6 +206,7 @@ mod signal {
     pub static SIGCHLD: libc::c_int = 20;
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     pub type sigset_t = u32;
     #[cfg(target_os = "freebsd")]
     pub struct sigset_t {
@@ -219,6 +225,7 @@ pub struct siginfo {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     pub struct sigaction {
         pub sa_handler: extern fn(libc::c_int),
         sa_tramp: *mut libc::c_void,
index fda9b7b1932b0a4b03477c4ecae18dfa2e4ae0de..f521934c0f9654056bba2036940f3e7758a82b44 100644 (file)
@@ -133,6 +133,7 @@ fn datasync(&mut self) -> IoResult<()> {
         return super::mkerr_libc(os_datasync(self.fd()));
 
         #[cfg(target_os = "macos")]
+        #[cfg(target_os = "ios")]
         fn os_datasync(fd: c_int) -> c_int {
             unsafe { libc::fcntl(fd, libc::F_FULLFSYNC) }
         }
@@ -140,7 +141,7 @@ fn os_datasync(fd: c_int) -> c_int {
         fn os_datasync(fd: c_int) -> c_int {
             retry(|| unsafe { libc::fdatasync(fd) })
         }
-        #[cfg(not(target_os = "macos"), not(target_os = "linux"))]
+        #[cfg(not(target_os = "macos"), not(target_os = "ios"), not(target_os = "linux"))]
         fn os_datasync(fd: c_int) -> c_int {
             retry(|| unsafe { libc::fsync(fd) })
         }
index 4158db7bb8ea1d902ef8fe40e67a1596f4d7d60c..6dc2482ab0c7df9b1e1ff58d0cf3a7eea72778fd 100644 (file)
@@ -50,6 +50,7 @@
 pub mod file;
 
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
 #[cfg(target_os = "android")]
 #[cfg(target_os = "linux")]
index e7effbd6bdbfb064ba935408f9cd0fc9a932b86d..30ea80a1296c7da6efcd237dc0b91561d6422aba 100644 (file)
@@ -320,6 +320,7 @@ fn set_keepalive(&mut self, seconds: Option<uint>) -> IoResult<()> {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> {
         setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPALIVE,
                    seconds as libc::c_int)
@@ -329,7 +330,7 @@ fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> {
         setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPIDLE,
                    seconds as libc::c_int)
     }
-    #[cfg(not(target_os = "macos"), not(target_os = "freebsd"))]
+    #[cfg(not(target_os = "macos"), not(target_os = "ios"), not(target_os = "freebsd"))]
     fn set_tcp_keepalive(&mut self, _seconds: uint) -> IoResult<()> {
         Ok(())
     }
index d8486cb9f0942c64cf7b101affebf09f7bb66d2d..f26d87ba1b52ff9f8853c7e54ef62b622768f5bc 100644 (file)
@@ -769,6 +769,7 @@ pub fn WTERMSIG(status: i32) -> i32 { status & 0x7f }
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     #[cfg(target_os = "freebsd")]
     mod imp {
         pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 }
index 11f9c4b3d8cb8cebe6ef32cdce12213125a0cbd8..ca0a810890c277cbf29aee3ad61bea693f30e8bb 100644 (file)
@@ -93,7 +93,20 @@ pub fn now() -> u64 {
     }
 }
 
-fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
+
+// Note: although the last parameter isn't used there is no way now to
+// convert it to unit type, because LLVM dies in SjLj preparation
+// step (unfortunately iOS uses SjLJ exceptions)
+//
+// It's definitely a temporary workaround just to get it working.
+// So far it looks like an LLVM issue and it was reported:
+// http://llvm.org/bugs/show_bug.cgi?id=19855
+// Actually this issue is pretty common while compiling for armv7 iOS
+// and in most cases it is simply solved by using --opt-level=2 (or -O)
+//
+// For this specific case unfortunately turning optimizations wasn't
+// enough.
+fn helper(input: libc::c_int, messages: Receiver<Req>, _: int) {
     let mut set: c::fd_set = unsafe { mem::zeroed() };
 
     let mut fd = FileDesc::new(input, true);
@@ -202,7 +215,9 @@ fn signal(active: &mut Vec<Box<Inner>>,
 
 impl Timer {
     pub fn new() -> IoResult<Timer> {
-        unsafe { HELPER.boot(|| {}, helper); }
+        // See notes above regarding using int return value
+        // instead of ()
+        unsafe { HELPER.boot(|| {0}, helper); }
 
         static mut ID: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
         let id = unsafe { ID.fetch_add(1, atomics::Relaxed) };
index e5e8126ace1841087957b8e79b0ac02470b7cbc5..7a944fd5abee2cfdaa076ea2a2b050698b9b1bf9 100644 (file)
@@ -34,6 +34,14 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -a0:0:64-n32".to_string()
           }
 
+          abi::OsiOS => {
+            "e-p:32:32:32\
+                -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
+                -f32:32:32-f64:64:64\
+                -v64:64:64-v128:64:128\
+                -a0:0:64-n32".to_string()
+          }
+
           abi::OsWin32 => {
             "e-p:32:32:32\
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
index 55998f254ed4a41c15867a45fea261e2bdd92c1c..ab4eda33d75b92d57d645a59008b83915c742337 100644 (file)
@@ -114,6 +114,13 @@ pub mod write {
     // which are *far* more efficient. This is obviously undesirable in some
     // cases, so if any sort of target feature is specified we don't append v7
     // to the feature list.
+    //
+    // On iOS only armv7 and newer are supported. So it is useful to
+    // get all hardware potential via VFP3 (hardware floating point)
+    // and NEON (SIMD) instructions supported by LLVM.
+    // Note that without those flags various linking errors might
+    // arise as some of intrinsicts are converted into function calls
+    // and nobody provides implementations those functions
     fn target_feature<'a>(sess: &'a Session) -> &'a str {
         match sess.targ_cfg.os {
             abi::OsAndroid => {
@@ -122,7 +129,10 @@ fn target_feature<'a>(sess: &'a Session) -> &'a str {
                 } else {
                     sess.opts.cg.target_feature.as_slice()
                 }
-            }
+            },
+            abi::OsiOS if sess.targ_cfg.arch == abi::Arm => {
+                "+v7,+thumb2,+vfp3,+neon"
+            },
             _ => sess.opts.cg.target_feature.as_slice()
         }
     }
@@ -827,15 +837,23 @@ pub fn filename_for_input(sess: &Session, crate_type: config::CrateType,
             out_filename.with_filename(format!("lib{}.rlib", libname))
         }
         config::CrateTypeDylib => {
-            let (prefix, suffix) = match sess.targ_cfg.os {
-                abi::OsWin32 => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX),
-                abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX),
-                abi::OsLinux => (loader::LINUX_DLL_PREFIX, loader::LINUX_DLL_SUFFIX),
-                abi::OsAndroid => (loader::ANDROID_DLL_PREFIX, loader::ANDROID_DLL_SUFFIX),
-                abi::OsFreebsd => (loader::FREEBSD_DLL_PREFIX, loader::FREEBSD_DLL_SUFFIX),
-            };
-            out_filename.with_filename(format!("{}{}{}", prefix, libname,
-                                               suffix))
+            // There is no support of DyLibs on iOS
+            if sess.targ_cfg.os == abi::OsiOS {
+                out_filename.with_filename(format!("lib{}.a", libname))
+            } else {
+                let (prefix, suffix) = match sess.targ_cfg.os {
+                    abi::OsWin32 => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX),
+                    abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX),
+                    abi::OsLinux => (loader::LINUX_DLL_PREFIX, loader::LINUX_DLL_SUFFIX),
+                    abi::OsAndroid => (loader::ANDROID_DLL_PREFIX, loader::ANDROID_DLL_SUFFIX),
+                    abi::OsFreebsd => (loader::FREEBSD_DLL_PREFIX, loader::FREEBSD_DLL_SUFFIX),
+                    abi::OsiOS => unreachable!(),
+                };
+                out_filename.with_filename(format!("{}{}{}",
+                                                   prefix,
+                                                   libname,
+                                                   suffix))
+            }
         }
         config::CrateTypeStaticlib => {
             out_filename.with_filename(format!("lib{}.a", libname))
@@ -886,7 +904,14 @@ fn link_binary_output(sess: &Session,
             link_natively(sess, trans, false, &obj_filename, &out_filename);
         }
         config::CrateTypeDylib => {
-            link_natively(sess, trans, true, &obj_filename, &out_filename);
+            if sess.targ_cfg.os == abi::OsiOS {
+                sess.warn(format!("No dylib for iOS -> saving static library {} to {}",
+                                  obj_filename.display(), out_filename.display()).as_slice());
+                link_staticlib(sess, &obj_filename, &out_filename);
+            }
+            else {
+                link_natively(sess, trans, true, &obj_filename, &out_filename);
+            }
         }
     }
 
@@ -991,7 +1016,7 @@ fn link_rlib<'a>(sess: &'a Session,
             // symbol table of the archive. This currently dies on OSX (see
             // #11162), and isn't necessary there anyway
             match sess.targ_cfg.os {
-                abi::OsMacos => {}
+                abi::OsMacos | abi::OsiOS => {}
                 _ => { a.update_symbols(); }
             }
         }
@@ -1104,15 +1129,16 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
 
     // On OSX, debuggers need this utility to get run to do some munging of
     // the symbols
-    if sess.targ_cfg.os == abi::OsMacos && (sess.opts.debuginfo != NoDebugInfo) {
-        match Command::new("dsymutil").arg(out_filename).status() {
-            Ok(..) => {}
-            Err(e) => {
-                sess.err(format!("failed to run dsymutil: {}", e).as_slice());
-                sess.abort_if_errors();
+    if (sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS)
+        && (sess.opts.debuginfo != NoDebugInfo) {
+            match Command::new("dsymutil").arg(out_filename).status() {
+                Ok(..) => {}
+                Err(e) => {
+                    sess.err(format!("failed to run dsymutil: {}", e).as_slice());
+                    sess.abort_if_errors();
+                }
             }
         }
-    }
 }
 
 fn link_args(cmd: &mut Command,
@@ -1169,7 +1195,7 @@ fn link_args(cmd: &mut Command,
     // already done the best it can do, and we also don't want to eliminate the
     // metadata. If we're building an executable, however, --gc-sections drops
     // the size of hello world from 1.8MB to 597K, a 67% reduction.
-    if !dylib && sess.targ_cfg.os != abi::OsMacos {
+    if !dylib && sess.targ_cfg.os != abi::OsMacos && sess.targ_cfg.os != abi::OsiOS {
         cmd.arg("-Wl,--gc-sections");
     }
 
@@ -1185,7 +1211,7 @@ fn link_args(cmd: &mut Command,
            sess.opts.optimize == config::Aggressive {
             cmd.arg("-Wl,-O1");
         }
-    } else if sess.targ_cfg.os == abi::OsMacos {
+    } else if sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS {
         // The dead_strip option to the linker specifies that functions and data
         // unreachable by the entry point will be removed. This is quite useful
         // with Rust's compilation model of compiling libraries at a time into
@@ -1348,7 +1374,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
     // For those that support this, we ensure we pass the option if the library
     // was flagged "static" (most defaults are dynamic) to ensure that if
     // libfoo.a and libfoo.so both exist that the right one is chosen.
-    let takes_hints = sess.targ_cfg.os != abi::OsMacos;
+    let takes_hints = sess.targ_cfg.os != abi::OsMacos && sess.targ_cfg.os != abi::OsiOS;
 
     for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() {
         match kind {
index 9f640a2c9cbe0eae2974c07b081cabc6610cc2bf..ea9879dbf492001a2683f6e68626628e053aac1d 100644 (file)
@@ -29,6 +29,14 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -a0:0:64-n32".to_string()
           }
 
+          abi::OsiOS => {
+            "E-p:32:32:32\
+                -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
+                -f32:32:32-f64:64:64\
+                -v64:64:64-v128:64:128\
+                -a0:0:64-n32".to_string()
+          }
+
           abi::OsWin32 => {
             "E-p:32:32:32\
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
index cdf49304f9a752a5255f3d372339f17041fd1623..a458cf22a5bdc3c545b2be4ab43899333c92e3e3 100644 (file)
@@ -122,7 +122,7 @@ pub fn get_rpath_relative_to_output(os: abi::Os,
         abi::OsAndroid | abi::OsLinux | abi::OsFreebsd
                           => "$ORIGIN",
         abi::OsMacos => "@loader_path",
-        abi::OsWin32 => unreachable!()
+        abi::OsWin32 | abi::OsiOS => unreachable!()
     };
 
     let mut lib = fs::realpath(&os::make_absolute(lib)).unwrap();
index 3ef013d47c91dc9837df7bc2e9a9926b407a0889..90106e9e0304643318dc2ed31ac9e0794e78f34b 100644 (file)
@@ -31,6 +31,14 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os)
                 -n8:16:32".to_string()
           }
 
+          abi::OsiOS => {
+            "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\
+                -i32:32:32-i64:32:64\
+                -f32:32:32-f64:32:64-v64:64:64\
+                -v128:128:128-a0:0:64-f80:128:128\
+                -n8:16:32".to_string()
+          }
+
           abi::OsWin32 => {
             "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32".to_string()
           }
index 80dd2b2c516294fa2d4e6b0d8b3713470356470f..55b0eca7be70c013487ba588f758269c86cb9a38 100644 (file)
@@ -28,6 +28,12 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 s0:64:64-f80:128:128-n8:16:32:64".to_string()
           }
 
+          abi::OsiOS => {
+            "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
+                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                s0:64:64-f80:128:128-n8:16:32:64".to_string()
+          }
+
           abi::OsWin32 => {
             // FIXME: Test this. Copied from linux (#2398)
             "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
index 186db839e33d861e6f0f65c76f164de83ae45dec..2f7dc136ef2ef680e9b8c97d5ae5dd9849d9fa4f 100644 (file)
@@ -362,7 +362,8 @@ pub fn cfg_os_to_meta_os(os: abi::Os) -> metadata::loader::Os {
         abi::OsLinux => loader::OsLinux,
         abi::OsAndroid => loader::OsAndroid,
         abi::OsMacos => loader::OsMacos,
-        abi::OsFreebsd => loader::OsFreebsd
+        abi::OsFreebsd => loader::OsFreebsd,
+        abi::OsiOS => loader::OsiOS,
     }
 }
 
@@ -373,6 +374,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
         abi::OsLinux =>   InternedString::new("linux"),
         abi::OsAndroid => InternedString::new("android"),
         abi::OsFreebsd => InternedString::new("freebsd"),
+        abi::OsiOS =>     InternedString::new("ios"),
     };
 
     // ARM is bi-endian, however using NDK seems to default
@@ -438,7 +440,8 @@ pub fn get_os(triple: &str) -> Option<abi::Os> {
     ("darwin",  abi::OsMacos),
     ("android", abi::OsAndroid),
     ("linux",   abi::OsLinux),
-    ("freebsd", abi::OsFreebsd)];
+    ("freebsd", abi::OsFreebsd),
+    ("ios",     abi::OsiOS)];
 
 pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
     for &(arch, abi) in architecture_abis.iter() {
index 773b9e6e0aac4022055e64b6cfea8afa95b38009..bc22b3ca7e242ecae8ae31e7eb9baf8a483e8af6 100644 (file)
@@ -249,4 +249,3 @@ pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> String)
               -> T {
     diagnostic::expect(sess.diagnostic(), opt, msg)
 }
-
index 4df21fbc974be7f20f78d5d57eab24c1ff7d19e6..63b177b0eb7149af4162cfe30464dff26ba3ac43 100644 (file)
@@ -215,7 +215,8 @@ fn visit_item(e: &Env, i: &ast::Item) {
                             Some(k) => {
                                 if k.equiv(&("static")) {
                                     cstore::NativeStatic
-                                } else if e.sess.targ_cfg.os == abi::OsMacos &&
+                                } else if (e.sess.targ_cfg.os == abi::OsMacos ||
+                                           e.sess.targ_cfg.os == abi::OsiOS) &&
                                           k.equiv(&("framework")) {
                                     cstore::NativeFramework
                                 } else if k.equiv(&("framework")) {
index cfda97ad26fd77860573621c224ec92743bd548d..a674b6cf5a91c0b84f3a469e7a9e8eabdad876d9 100644 (file)
@@ -39,6 +39,9 @@
 pub static MACOS_DLL_PREFIX: &'static str = "lib";
 pub static MACOS_DLL_SUFFIX: &'static str = ".dylib";
 
+pub static IOS_DLL_PREFIX: &'static str = "lib";
+pub static IOS_DLL_SUFFIX: &'static str = ".dylib";
+
 pub static WIN32_DLL_PREFIX: &'static str = "";
 pub static WIN32_DLL_SUFFIX: &'static str = ".dll";
 
@@ -56,7 +59,8 @@ pub enum Os {
     OsWin32,
     OsLinux,
     OsAndroid,
-    OsFreebsd
+    OsFreebsd,
+    OsiOS
 }
 
 pub struct CrateMismatch {
@@ -455,6 +459,7 @@ fn dylibname(&self) -> (&'static str, &'static str) {
             OsLinux => (LINUX_DLL_PREFIX, LINUX_DLL_SUFFIX),
             OsAndroid => (ANDROID_DLL_PREFIX, ANDROID_DLL_SUFFIX),
             OsFreebsd => (FREEBSD_DLL_PREFIX, FREEBSD_DLL_SUFFIX),
+            OsiOS => (IOS_DLL_PREFIX, IOS_DLL_SUFFIX),
         }
     }
 
@@ -593,6 +598,7 @@ fn get_metadata_section_imp(os: Os, filename: &Path) -> Result<MetadataBlob, Str
 pub fn meta_section_name(os: Os) -> &'static str {
     match os {
         OsMacos => "__DATA,__note.rustc",
+        OsiOS => "__DATA,__note.rustc",
         OsWin32 => ".note.rustc",
         OsLinux => ".note.rustc",
         OsAndroid => ".note.rustc",
@@ -603,6 +609,7 @@ pub fn meta_section_name(os: Os) -> &'static str {
 pub fn read_meta_section_name(os: Os) -> &'static str {
     match os {
         OsMacos => "__note.rustc",
+        OsiOS => "__note.rustc",
         OsWin32 => ".note.rustc",
         OsLinux => ".note.rustc",
         OsAndroid => ".note.rustc",
index 93b6fdd8988c5f2a399a3ed68fbc71af9287205b..d10f6b72820d29c68b77c9e21e29edb009062728 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-use syntax::abi::{OsWin32, OsMacos};
+use syntax::abi::{OsWin32, OsMacos, OsiOS};
 use lib::llvm::*;
 use super::cabi::*;
 use super::common::*;
@@ -36,7 +36,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
 
         enum Strategy { RetValue(Type), RetPointer }
         let strategy = match ccx.sess().targ_cfg.os {
-            OsWin32 | OsMacos => {
+            OsWin32 | OsMacos | OsiOS => {
                 match llsize_of_alloc(ccx, rty) {
                     1 => RetValue(Type::i8(ccx)),
                     2 => RetValue(Type::i16(ccx)),
index b28db3d378be7dcfd574ce6c7c21ea83bdfb95f1..24f30bae75a91fb762330adda0cea01b9bb50bc4 100644 (file)
@@ -680,7 +680,7 @@ fn get_or_create_landing_pad(&'a self) -> BasicBlockRef {
                     Some(llpersonality) => llpersonality,
                     None => {
                         let fty = Type::variadic_func(&[], &Type::i32(self.ccx));
-                        let f = base::decl_cdecl_fn(self.ccx.llmod,
+                        let f = base::decl_cdecl_fn(self.ccx,
                                                     "rust_eh_personality",
                                                     fty,
                                                     ty::mk_i32());
index db17000abb32b188c26477794b18e29de05e22d4..c50badac531a947efad87bae1c6bdf90d5ebe704 100644 (file)
@@ -277,7 +277,8 @@ pub fn finalize(cx: &CrateContext) {
         // instruct LLVM to emit an older version of dwarf, however,
         // for OS X to understand. For more info see #11352
         // This can be overridden using --llvm-opts -dwarf-version,N.
-        if cx.sess().targ_cfg.os == abi::OsMacos {
+        if cx.sess().targ_cfg.os == abi::OsMacos ||
+            cx.sess().targ_cfg.os == abi::OsiOS {
             "Dwarf Version".with_c_str(
                 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2));
         } else {
index 8ad10a686e677677778e4ce92efb73b5f6424094..800e7f065f1e604ef7422dd273629c89e93ae321 100644 (file)
@@ -64,6 +64,7 @@ pub struct flock {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     mod os {
         use libc;
 
index 0789bf7f906f6928749e7e8522c97d760cc7f8ec..d6d4b18051bf3e54ffaad90c02f75cf67810ab99 100644 (file)
@@ -145,6 +145,7 @@ fn smoke_test() {
 }
 
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 #[cfg(target_os = "win32")]
 mod imp {
     use core::prelude::*;
index 76cbeef443eaefa4be1194fb1599dbc90c6e31c0..e17a43322ba3732458e2e94080d650142f998b63 100644 (file)
@@ -164,7 +164,7 @@ pub unsafe fn cleanup() {
 pub mod shouldnt_be_public {
     #[cfg(not(test))]
     pub use super::local_ptr::native::maybe_tls_key;
-    #[cfg(not(windows), not(target_os = "android"))]
+    #[cfg(not(windows), not(target_os = "android"), not(target_os = "ios"))]
     pub use super::local_ptr::compiled::RT_TLS_PTR;
 }
 
index 846ec248805e96d5e940f6d9d3b45f80e12a4709..50c2aba2b5cb11abed98276e1d9d5c4f4a2254ff 100644 (file)
@@ -17,6 +17,7 @@
 use libc;
 
 #[cfg(not(target_arch = "arm"))]
+#[cfg(target_os = "ios")]
 #[repr(C)]
 pub enum _Unwind_Action {
     _UA_SEARCH_PHASE = 1,
@@ -61,9 +62,12 @@ pub enum _Unwind_Reason_Code {
 #[cfg(target_arch = "x86_64")]
 pub static unwinder_private_data_size: int = 2;
 
-#[cfg(target_arch = "arm")]
+#[cfg(target_arch = "arm", not(target_os = "ios"))]
 pub static unwinder_private_data_size: int = 20;
 
+#[cfg(target_arch = "arm", target_os = "ios")]
+pub static unwinder_private_data_size: int = 5;
+
 #[cfg(target_arch = "mips")]
 pub static unwinder_private_data_size: int = 2;
 
@@ -89,8 +93,27 @@ pub enum _Unwind_Context {}
 #[link(name = "gcc")]
 extern {}
 
+
 extern "C" {
+    // iOS on armv7 uses SjLj exceptions and requires to link
+    // agains corresponding routine (..._SjLj_...)
+    // So here we just skip linking for iOS
+    #[cfg(not(target_os = "ios", target_arch = "arm"))]
     pub fn _Unwind_RaiseException(exception: *_Unwind_Exception)
                 -> _Unwind_Reason_Code;
     pub fn _Unwind_DeleteException(exception: *_Unwind_Exception);
 }
+
+// ... and now we just providing access to SjLj counterspart
+// through a standard name to hide those details from others
+// (see also comment above regarding _Unwind_RaiseException)
+#[cfg(target_os = "ios", target_arch = "arm")]
+#[inline(always)]
+pub unsafe fn _Unwind_RaiseException(exc: *_Unwind_Exception)
+                                     -> _Unwind_Reason_Code {
+    extern "C" {
+        fn _Unwind_SjLj_RaiseException(e: *_Unwind_Exception)
+                                       -> _Unwind_Reason_Code; }
+
+    _Unwind_SjLj_RaiseException(exc)
+}
index 91e3409892ea5f3d2da7027a57409f3429948794..b6858be32b7ceb70fc0ee9f4da000dc9d8e18f09 100644 (file)
 
 #[cfg(windows)]               // mingw-w32 doesn't like thread_local things
 #[cfg(target_os = "android")] // see #10686
+#[cfg(target_os = "ios")]
 pub use self::native::{init, cleanup, put, take, try_take, unsafe_take, exists,
                        unsafe_borrow, try_unsafe_borrow};
 
-#[cfg(not(windows), not(target_os = "android"))]
+#[cfg(not(windows), not(target_os = "android"), not(target_os = "ios"))]
 pub use self::compiled::{init, cleanup, put, take, try_take, unsafe_take, exists,
                          unsafe_borrow, try_unsafe_borrow};
 
@@ -81,7 +82,7 @@ pub unsafe fn borrow<T>() -> Borrowed<T> {
 /// implemented using LLVM's thread_local attribute which isn't necessarily
 /// working on all platforms. This implementation is faster, however, so we use
 /// it wherever possible.
-#[cfg(not(windows), not(target_os = "android"))]
+#[cfg(not(windows), not(target_os = "android"), not(target_os = "ios"))]
 pub mod compiled {
     use core::prelude::*;
 
index eec19e9d5db86bf9cb5ad55587516b9a2b668d40..26359ff7f6e9a25d628f5b9477fc9b2c2a53623a 100644 (file)
@@ -283,6 +283,7 @@ mod os {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     mod os {
         use libc;
 
@@ -294,6 +295,10 @@ mod os {
         static __PTHREAD_MUTEX_SIZE__: uint = 40;
         #[cfg(target_arch = "x86")]
         static __PTHREAD_COND_SIZE__: uint = 24;
+        #[cfg(target_arch = "arm")]
+        static __PTHREAD_MUTEX_SIZE__: uint = 40;
+        #[cfg(target_arch = "arm")]
+        static __PTHREAD_COND_SIZE__: uint = 24;
 
         static _PTHREAD_MUTEX_SIG_init: libc::c_long = 0x32AAABA7;
         static _PTHREAD_COND_SIG_init: libc::c_long = 0x3CB0B1BB;
index aac773f6f859e685763b24b1ce63d1bb07142d83..e6fa845bedc895aee2710029db29254dda429a88 100644 (file)
@@ -173,7 +173,8 @@ pub unsafe fn record_sp_limit(limit: uint) {
     return target_record_sp_limit(limit);
 
     // x86-64
-    #[cfg(target_arch = "x86_64", target_os = "macos")] #[inline(always)]
+    #[cfg(target_arch = "x86_64", target_os = "macos")]
+    #[cfg(target_arch = "x86_64", target_os = "ios")] #[inline(always)]
     unsafe fn target_record_sp_limit(limit: uint) {
         asm!("movq $$0x60+90*8, %rsi
               movq $0, %gs:(%rsi)" :: "r"(limit) : "rsi" : "volatile")
@@ -195,7 +196,8 @@ unsafe fn target_record_sp_limit(limit: uint) {
     }
 
     // x86
-    #[cfg(target_arch = "x86", target_os = "macos")] #[inline(always)]
+    #[cfg(target_arch = "x86", target_os = "macos")]
+    #[cfg(target_arch = "x86", target_os = "ios")] #[inline(always)]
     unsafe fn target_record_sp_limit(limit: uint) {
         asm!("movl $$0x48+90*4, %eax
               movl $0, %gs:(%eax)" :: "r"(limit) : "eax" : "volatile")
@@ -243,7 +245,8 @@ pub unsafe fn get_sp_limit() -> uint {
     return target_get_sp_limit();
 
     // x86-64
-    #[cfg(target_arch = "x86_64", target_os = "macos")] #[inline(always)]
+    #[cfg(target_arch = "x86_64", target_os = "macos")]
+    #[cfg(target_arch = "x86_64", target_os = "ios")] #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
         let limit;
         asm!("movq $$0x60+90*8, %rsi
@@ -270,7 +273,8 @@ unsafe fn target_get_sp_limit() -> uint {
     }
 
     // x86
-    #[cfg(target_arch = "x86", target_os = "macos")] #[inline(always)]
+    #[cfg(target_arch = "x86", target_os = "macos")]
+    #[cfg(target_arch = "x86", target_os = "ios")] #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
         let limit;
         asm!("movl $$0x48+90*4, %eax
index 4ef2cec19db9b01d21618d12d2947d2e06b7453e..3dcd1c4a6f0d3bde6b7a16392d34a2fd773c1319 100644 (file)
@@ -276,7 +276,6 @@ pub unsafe fn detach(native: rust_thread) {
     }
 
     pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); }
-
     // glibc >= 2.15 has a __pthread_get_minstack() function that returns
     // PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
     // storage.  We need that information to avoid blowing up when a small stack
@@ -345,4 +344,3 @@ fn small_stacks() {
         assert_eq!(42, Thread::start_stack(1, proc () 42).join());
     }
 }
-
index 2cdeb21fb83dde04f3dfd25c63d2b7577863764f..4a7be39e6b87a0b7e15891acb87cd58bdc604fbe 100644 (file)
@@ -37,13 +37,14 @@ pub unsafe fn destroy(key: Key) {
     assert!(pthread_key_delete(key) == 0);
 }
 
-#[cfg(target_os="macos")]
+#[cfg(target_os = "macos")]
 #[allow(non_camel_case_types)] // foreign type
 type pthread_key_t = ::libc::c_ulong;
 
 #[cfg(target_os="linux")]
 #[cfg(target_os="freebsd")]
 #[cfg(target_os="android")]
+#[cfg(target_os = "ios")]
 #[allow(non_camel_case_types)] // foreign type
 type pthread_key_t = ::libc::c_uint;
 
index f7475db1552f7181acd5bd414aca32e0d7ecd290..e60c50f0adb43b6d063177e1f60dce5b6cd9cc3a 100644 (file)
@@ -285,16 +285,74 @@ pub extern "C" fn rust_eh_personality_catch(
         }
         else { // cleanup phase
             unsafe {
-                 __gcc_personality_v0(version, actions, exception_class, ue_header,
+                __gcc_personality_v0(version, actions, exception_class, ue_header,
+                                     context)
+            }
+        }
+    }
+}
+
+// iOS on armv7 is using SjLj exceptions and therefore requires to use
+// a specialized personality routine: __gcc_personality_sj0
+
+#[cfg(target_os = "ios", target_arch = "arm", not(test))]
+#[doc(hidden)]
+#[allow(visible_private_types)]
+pub mod eabi {
+    use uw = libunwind;
+    use libc::c_int;
+
+    extern "C" {
+        #[cfg(target_os = "ios", target_arch = "arm")]
+        fn __gcc_personality_sj0(version: c_int,
+                                actions: uw::_Unwind_Action,
+                                exception_class: uw::_Unwind_Exception_Class,
+                                ue_header: *uw::_Unwind_Exception,
+                                context: *uw::_Unwind_Context)
+            -> uw::_Unwind_Reason_Code;
+    }
+
+    #[lang="eh_personality"]
+    #[no_mangle] // so we can reference it by name from middle/trans/base.rs
+    pub extern "C" fn rust_eh_personality(
+        version: c_int,
+        actions: uw::_Unwind_Action,
+        exception_class: uw::_Unwind_Exception_Class,
+        ue_header: *uw::_Unwind_Exception,
+        context: *uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        unsafe {
+            __gcc_personality_sj0(version, actions, exception_class, ue_header,
+                                  context)
+        }
+    }
+
+    #[no_mangle] // referenced from rust_try.ll
+    pub extern "C" fn rust_eh_personality_catch(
+        version: c_int,
+        actions: uw::_Unwind_Action,
+        exception_class: uw::_Unwind_Exception_Class,
+        ue_header: *uw::_Unwind_Exception,
+        context: *uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
+            uw::_URC_HANDLER_FOUND // catch!
+        }
+        else { // cleanup phase
+            unsafe {
+                __gcc_personality_sj0(version, actions, exception_class, ue_header,
                                       context)
             }
         }
     }
 }
 
+
 // ARM EHABI uses a slightly different personality routine signature,
 // but otherwise works the same.
-#[cfg(target_arch = "arm", not(test))]
+#[cfg(target_arch = "arm", not(test), not(target_os = "ios"))]
 #[allow(visible_private_types)]
 pub mod eabi {
     use uw = libunwind;
@@ -332,7 +390,7 @@ pub extern "C" fn rust_eh_personality_catch(
         }
         else { // cleanup phase
             unsafe {
-                 __gcc_personality_v0(state, ue_header, context)
+                __gcc_personality_v0(state, ue_header, context)
             }
         }
     }
index fa6efc8a4b18ab34e0b75ce8913ee8c28844e057..5dbed6844c35fb5d77184b9a50c67aabb82270e4 100644 (file)
@@ -153,7 +153,7 @@ pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, String> {
     }
 }
 
-#[cfg(test)]
+#[cfg(test, not(target_os = "ios"))]
 mod test {
     use super::*;
     use prelude::*;
@@ -205,6 +205,7 @@ fn test_errors_do_not_crash() {
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "android")]
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
 pub mod dl {
     use prelude::*;
index cc76cde7baffc6ec1007d102e6c8756ac2ff0e12..f6b1c04dd34c604b5beec2a99e601f5caadf62c3 100644 (file)
@@ -552,6 +552,7 @@ pub fn pipe() -> Pipe {
 
 /// Returns the proper dll filename for the given basename of a file
 /// as a String.
+#[cfg(not(target_os="ios"))]
 pub fn dll_filename(base: &str) -> String {
     format!("{}{}{}", consts::DLL_PREFIX, base, consts::DLL_SUFFIX)
 }
@@ -608,6 +609,7 @@ fn load_self() -> Option<Vec<u8>> {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     fn load_self() -> Option<Vec<u8>> {
         unsafe {
             use libc::funcs::extra::_NSGetExecutablePath;
@@ -802,6 +804,7 @@ fn chdir(p: &Path) -> bool {
 /// Returns the platform-specific value of errno
 pub fn errno() -> int {
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     #[cfg(target_os = "freebsd")]
     fn errno_location() -> *c_int {
         extern {
@@ -850,6 +853,7 @@ pub fn error_string(errnum: uint) -> String {
     #[cfg(unix)]
     fn strerror(errnum: uint) -> String {
         #[cfg(target_os = "macos")]
+        #[cfg(target_os = "ios")]
         #[cfg(target_os = "android")]
         #[cfg(target_os = "freebsd")]
         fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t)
@@ -995,6 +999,64 @@ fn real_args_as_bytes() -> Vec<Vec<u8>> {
     }
 }
 
+// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
+// and use underscores in their names - they're most probably
+// are considered private and therefore should be avoided
+// Here is another way to get arguments using Objective C
+// runtime
+//
+// In general it looks like:
+// res = Vec::new()
+// let args = [[NSProcessInfo processInfo] arguments]
+// for i in range(0, [args count])
+//      res.push([args objectAtIndex:i])
+// res
+#[cfg(target_os = "ios")]
+fn real_args_as_bytes() -> Vec<Vec<u8>> {
+    use c_str::CString;
+    use iter::range;
+    use mem;
+
+    #[link(name = "objc")]
+    extern {
+        fn sel_registerName(name: *libc::c_uchar) -> Sel;
+        fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId;
+        fn objc_getClass(class_name: *libc::c_uchar) -> NsId;
+    }
+
+    #[link(name = "Foundation", kind = "framework")]
+    extern {}
+
+    type Sel = *libc::c_void;
+    type NsId = *libc::c_void;
+
+    let mut res = Vec::new();
+
+    unsafe {
+        let processInfoSel = sel_registerName("processInfo\0".as_ptr());
+        let argumentsSel = sel_registerName("arguments\0".as_ptr());
+        let utf8Sel = sel_registerName("UTF8String\0".as_ptr());
+        let countSel = sel_registerName("count\0".as_ptr());
+        let objectAtSel = sel_registerName("objectAtIndex:\0".as_ptr());
+
+        let klass = objc_getClass("NSProcessInfo\0".as_ptr());
+        let info = objc_msgSend(klass, processInfoSel);
+        let args = objc_msgSend(info, argumentsSel);
+
+        let cnt: int = mem::transmute(objc_msgSend(args, countSel));
+        for i in range(0, cnt) {
+            let tmp = objc_msgSend(args, objectAtSel, i);
+            let utf_c_str: *libc::c_char = mem::transmute(objc_msgSend(tmp, utf8Sel));
+            let s = CString::new(utf_c_str, false);
+            if s.is_not_null() {
+                res.push(Vec::from_slice(s.as_bytes_no_nul()))
+            }
+        }
+    }
+
+    res
+}
+
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "android")]
 #[cfg(target_os = "freebsd")]
@@ -1532,6 +1594,25 @@ pub mod consts {
     pub static EXE_EXTENSION: &'static str = "";
 }
 
+#[cfg(target_os = "ios")]
+pub mod consts {
+    pub use os::arch_consts::ARCH;
+
+    pub static FAMILY: &'static str = "unix";
+
+    /// A string describing the specific operating system in use: in this
+    /// case, `ios`.
+    pub static SYSNAME: &'static str = "ios";
+
+    /// Specifies the filename suffix used for executable binaries on this
+    /// platform: in this case, the empty string.
+    pub static EXE_SUFFIX: &'static str = "";
+
+    /// Specifies the file extension, if any, used for executable binaries
+    /// on this platform: in this case, the empty string.
+    pub static EXE_EXTENSION: &'static str = "";
+}
+
 #[cfg(target_os = "freebsd")]
 pub mod consts {
     pub use os::arch_consts::ARCH;
index 2654b7a1acc6af5145592e931b67a66e1ccb071d..f507011c2b955166e5863b85aee4aa306e8b7444 100644 (file)
@@ -13,7 +13,7 @@
 
 pub use self::imp::OsRng;
 
-#[cfg(unix)]
+#[cfg(unix, not(target_os = "ios"))]
 mod imp {
     use io::{IoResult, File};
     use path::Path;
@@ -28,7 +28,7 @@ mod imp {
     ///   `/dev/urandom`.
     /// - Windows: calls `CryptGenRandom`, using the default cryptographic
     ///   service provider with the `PROV_RSA_FULL` type.
-    ///
+    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
     /// This does not block.
     #[cfg(unix)]
     pub struct OsRng {
@@ -58,6 +58,71 @@ fn fill_bytes(&mut self, v: &mut [u8]) {
     }
 }
 
+#[cfg(target_os = "ios")]
+mod imp {
+    extern crate libc;
+
+    use collections::Collection;
+    use io::{IoResult};
+    use kinds::marker;
+    use mem;
+    use os;
+    use rand::Rng;
+    use result::{Ok};
+    use self::libc::{c_int, size_t};
+    use slice::MutableVector;
+
+    /// A random number generator that retrieves randomness straight from
+    /// the operating system. Platform sources:
+    ///
+    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
+    ///   `/dev/urandom`.
+    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
+    ///   service provider with the `PROV_RSA_FULL` type.
+    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
+    /// This does not block.
+    pub struct OsRng {
+        marker: marker::NoCopy
+    }
+
+    struct SecRandom;
+
+    static kSecRandomDefault: *SecRandom = 0 as *SecRandom;
+
+    #[link(name = "Security", kind = "framework")]
+    extern "C" {
+        fn SecRandomCopyBytes(rnd: *SecRandom, count: size_t, bytes: *mut u8) -> c_int;
+    }
+
+    impl OsRng {
+        /// Create a new `OsRng`.
+        pub fn new() -> IoResult<OsRng> {
+            Ok(OsRng {marker: marker::NoCopy} )
+        }
+    }
+
+    impl Rng for OsRng {
+        fn next_u32(&mut self) -> u32 {
+            let mut v = [0u8, .. 4];
+            self.fill_bytes(v);
+            unsafe { mem::transmute(v) }
+        }
+        fn next_u64(&mut self) -> u64 {
+            let mut v = [0u8, .. 8];
+            self.fill_bytes(v);
+            unsafe { mem::transmute(v) }
+        }
+        fn fill_bytes(&mut self, v: &mut [u8]) {
+            let ret = unsafe {
+                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
+            };
+            if ret == -1 {
+                fail!("couldn't generate random bytes: {}", os::last_os_error());
+            }
+        }
+    }
+}
+
 #[cfg(windows)]
 mod imp {
     extern crate libc;
index a1372b51d472a51e5e1b5bc8785d15ffd2e0451c..16b598b3ae7b9dfbcee72f3db8764dab53b4010e 100644 (file)
@@ -237,22 +237,58 @@ macro_rules! demangle(
 #[cfg(unix)]
 mod imp {
     use c_str::CString;
-    use io::{IoResult, IoError, Writer};
+    use io::{IoResult, Writer};
     use libc;
     use mem;
     use option::{Some, None, Option};
     use result::{Ok, Err};
     use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
 
-    struct Context<'a> {
-        idx: int,
-        writer: &'a mut Writer,
-        last_error: Option<IoError>,
+    /// As always - iOS on arm uses SjLj exceptions and
+    /// _Unwind_Backtrace is even not available there. Still,
+    /// backtraces could be extracted using a backtrace function,
+    /// which thanks god is public
+    #[cfg(target_os = "ios", target_arch = "arm")]
+    #[inline(never)]
+    pub fn write(w: &mut Writer) -> IoResult<()> {
+        use iter::{Iterator, range};
+        use result;
+        use slice::{MutableVector};
+
+        extern {
+            fn backtrace(buf: *mut *libc::c_void, sz: libc::c_int) -> libc::c_int;
+        }
+
+        // while it doesn't requires lock for work as everything is
+        // local, it still displays much nicier backtraces when a
+        // couple of tasks fail simultaneously
+        static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
+        let _g = unsafe { LOCK.lock() };
+
+        try!(writeln!(w, "stack backtrace:"));
+        // 100 lines should be enough
+        static size: libc::c_int = 100;
+        let mut buf: [*libc::c_void, ..size] = unsafe {mem::zeroed()};
+        let cnt = unsafe { backtrace(buf.as_mut_ptr(), size) as uint};
+
+        // skipping the first one as it is write itself
+        result::fold_(range(1, cnt).map(|i| {
+            print(w, i as int, buf[i])
+        }))
     }
 
+    #[cfg(not(target_os = "ios", target_arch = "arm"))]
     #[inline(never)] // if we know this is a function call, we can skip it when
                      // tracing
     pub fn write(w: &mut Writer) -> IoResult<()> {
+        use io::IoError;
+
+        struct Context<'a> {
+            idx: int,
+            writer: &'a mut Writer,
+            last_error: Option<IoError>,
+        }
+
         // When using libbacktrace, we use some necessary global state, so we
         // need to prevent more than one thread from entering this block. This
         // is semi-reasonable in terms of printing anyway, and we know that all
@@ -291,7 +327,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> {
             // instructions after it. This means that the return instruction
             // pointer points *outside* of the calling function, and by
             // unwinding it we go back to the original function.
-            let ip = if cfg!(target_os = "macos") {
+            let ip = if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
                 ip
             } else {
                 unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
@@ -323,6 +359,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> {
         use intrinsics;
         #[repr(C)]
@@ -347,7 +384,7 @@ fn dladdr(addr: *libc::c_void,
         }
     }
 
-    #[cfg(not(target_os = "macos"))]
+    #[cfg(not(target_os = "macos"), not(target_os = "ios"))]
     fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> {
         use collections::Collection;
         use iter::Iterator;
@@ -487,9 +524,14 @@ fn output(w: &mut Writer, idx: int, addr: *libc::c_void,
 
     /// Unwind library interface used for backtraces
     ///
-    /// Note that the native libraries come from librustrt, not this module.
+    /// Note that the native libraries come from librustrt, not this
+    /// module.
+    /// Note that dead code is allowed as here are just bindings
+    /// iOS doesn't use all of them it but adding more
+    /// platform-specific configs pollutes the code too much
     #[allow(non_camel_case_types)]
     #[allow(non_snake_case_functions)]
+    #[allow(dead_code)]
     mod uw {
         use libc;
 
@@ -514,6 +556,8 @@ pub enum _Unwind_Context {}
                           arg: *libc::c_void) -> _Unwind_Reason_Code;
 
         extern {
+            // No native _Unwind_Backtrace on iOS
+            #[cfg(not(target_os = "ios", target_arch = "arm"))]
             pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
                                      trace_argument: *libc::c_void)
                         -> _Unwind_Reason_Code;
index c804918ae4b411fd74f364cb702ff6d73dc5d189..f8bfde52261632f1887ccffe786d263f9b4d45e3 100644 (file)
@@ -39,3 +39,7 @@
 #[cfg(target_os = "macos")]
 #[link(name = "System")]
 extern {}
+
+#[cfg(target_os = "ios")]
+#[link(name = "System")]
+extern {}
index cfe85995df69b08d8d97b46b8bf795298e75b114..ec54a033e715321a14365a5dfd7533dd17818c37 100644 (file)
@@ -11,7 +11,7 @@
 use std::fmt;
 
 #[deriving(PartialEq)]
-pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, }
+pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, OsiOS, }
 
 #[deriving(PartialEq, Eq, Hash, Encodable, Decodable, Clone)]
 pub enum Abi {
index 63523cd3a6f6a877482e2da76f4d5743e3f515fa..b4a2e92cc1262a02660c2778f72a124c07783583 100644 (file)
@@ -48,7 +48,7 @@ mod rustrt {
     }
 }
 
-#[cfg(unix, not(target_os = "macos"))]
+#[cfg(unix, not(target_os = "macos"), not(target_os = "ios"))]
 mod imp {
     use libc::{c_int, timespec};
 
@@ -63,6 +63,7 @@ mod imp {
 
 }
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 mod imp {
     use libc::{timeval, timezone, c_int, mach_timebase_info};
 
@@ -123,6 +124,7 @@ unsafe fn os_get_time() -> (i64, i32) {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     unsafe fn os_get_time() -> (i64, i32) {
         use std::ptr;
         let mut tv = libc::timeval { tv_sec: 0, tv_usec: 0 };
@@ -130,7 +132,7 @@ unsafe fn os_get_time() -> (i64, i32) {
         (tv.tv_sec as i64, tv.tv_usec * 1000)
     }
 
-    #[cfg(not(target_os = "macos"), not(windows))]
+    #[cfg(not(target_os = "macos"), not(target_os = "ios"), not(windows))]
     unsafe fn os_get_time() -> (i64, i32) {
         let mut tv = libc::timespec { tv_sec: 0, tv_nsec: 0 };
         imp::clock_gettime(libc::CLOCK_REALTIME, &mut tv);
@@ -162,6 +164,7 @@ fn os_precise_time_ns() -> u64 {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     fn os_precise_time_ns() -> u64 {
         static mut TIMEBASE: libc::mach_timebase_info = libc::mach_timebase_info { numer: 0,
                                                                                    denom: 0 };
@@ -175,7 +178,7 @@ fn os_precise_time_ns() -> u64 {
         }
     }
 
-    #[cfg(not(windows), not(target_os = "macos"))]
+    #[cfg(not(windows), not(target_os = "macos"), not(target_os = "ios"))]
     fn os_precise_time_ns() -> u64 {
         let mut ts = libc::timespec { tv_sec: 0, tv_nsec: 0 };
         unsafe {