about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/liblibc/lib.rs13
-rw-r--r--src/libnative/io/c_unix.rs7
-rw-r--r--src/libnative/io/file_unix.rs3
-rw-r--r--src/libnative/io/mod.rs1
-rw-r--r--src/libnative/io/net.rs3
-rw-r--r--src/libnative/io/process.rs1
-rw-r--r--src/libnative/io/timer_unix.rs19
-rw-r--r--src/librustc/back/arm.rs8
-rw-r--r--src/librustc/back/link.rs70
-rw-r--r--src/librustc/back/mips.rs8
-rw-r--r--src/librustc/back/rpath.rs2
-rw-r--r--src/librustc/back/x86.rs8
-rw-r--r--src/librustc/back/x86_64.rs6
-rw-r--r--src/librustc/driver/config.rs7
-rw-r--r--src/librustc/driver/session.rs1
-rw-r--r--src/librustc/metadata/creader.rs3
-rw-r--r--src/librustc/metadata/loader.rs9
-rw-r--r--src/librustc/middle/trans/cabi_x86.rs4
-rw-r--r--src/librustc/middle/trans/cleanup.rs2
-rw-r--r--src/librustc/middle/trans/debuginfo.rs3
-rw-r--r--src/librustdoc/flock.rs1
-rw-r--r--src/librustrt/args.rs1
-rw-r--r--src/librustrt/lib.rs2
-rw-r--r--src/librustrt/libunwind.rs25
-rw-r--r--src/librustrt/local_ptr.rs5
-rw-r--r--src/librustrt/mutex.rs5
-rw-r--r--src/librustrt/stack.rs12
-rw-r--r--src/librustrt/thread.rs2
-rw-r--r--src/librustrt/thread_local_storage.rs3
-rw-r--r--src/librustrt/unwind.rs64
-rw-r--r--src/libstd/dynamic_lib.rs3
-rw-r--r--src/libstd/os.rs81
-rw-r--r--src/libstd/rand/os.rs69
-rw-r--r--src/libstd/rt/backtrace.rs60
-rw-r--r--src/libstd/rtdeps.rs4
-rw-r--r--src/libsyntax/abi.rs2
-rw-r--r--src/libtime/lib.rs9
37 files changed, 461 insertions, 65 deletions
diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs
index ff87b7fb007..9ed0d50a03e 100644
--- a/src/liblibc/lib.rs
+++ b/src/liblibc/lib.rs
@@ -278,10 +278,13 @@ pub use consts::os::extra::{MAP_STACK};
 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 mod types {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     pub mod os {
         pub mod common {
             pub mod posix01 {
@@ -3106,6 +3110,7 @@ pub mod consts {
     }
 
     #[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 funcs {
     #[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 funcs {
                 #[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 funcs {
                 #[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 mod funcs {
     #[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 funcs {
                 #[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 funcs {
     #[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 mod funcs {
     }
 
     #[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 funcs {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     pub mod extra {
         use types::os::arch::c95::{c_char, c_int};
 
diff --git a/src/libnative/io/c_unix.rs b/src/libnative/io/c_unix.rs
index e6cb5cb76f1..70fd6310070 100644
--- a/src/libnative/io/c_unix.rs
+++ b/src/libnative/io/c_unix.rs
@@ -20,6 +20,7 @@ pub use self::signal::{SA_NODEFER, SA_NOCLDWAIT, SA_SIGINFO, SIGCHLD};
 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 = 0x5421;
 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 = 0x5451;
 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 @@ extern {
 }
 
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 mod select {
     pub static FD_SETSIZE: uint = 1024;
 
@@ -187,6 +191,7 @@ mod signal {
 }
 
 #[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 @@ mod signal {
     }
 
     #[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,
diff --git a/src/libnative/io/file_unix.rs b/src/libnative/io/file_unix.rs
index fda9b7b1932..f521934c0f9 100644
--- a/src/libnative/io/file_unix.rs
+++ b/src/libnative/io/file_unix.rs
@@ -133,6 +133,7 @@ impl rtio::RtioFileStream for FileDesc {
         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 @@ impl rtio::RtioFileStream for FileDesc {
         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) })
         }
diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs
index 4158db7bb8e..6dc2482ab0c 100644
--- a/src/libnative/io/mod.rs
+++ b/src/libnative/io/mod.rs
@@ -50,6 +50,7 @@ pub mod file;
 pub mod file;
 
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 #[cfg(target_os = "freebsd")]
 #[cfg(target_os = "android")]
 #[cfg(target_os = "linux")]
diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs
index e7effbd6bdb..30ea80a1296 100644
--- a/src/libnative/io/net.rs
+++ b/src/libnative/io/net.rs
@@ -320,6 +320,7 @@ impl TcpStream {
     }
 
     #[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 @@ impl TcpStream {
         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(())
     }
diff --git a/src/libnative/io/process.rs b/src/libnative/io/process.rs
index d8486cb9f09..f26d87ba1b5 100644
--- a/src/libnative/io/process.rs
+++ b/src/libnative/io/process.rs
@@ -769,6 +769,7 @@ fn translate_status(status: c_int) -> rtio::ProcessExit {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     #[cfg(target_os = "freebsd")]
     mod imp {
         pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 }
diff --git a/src/libnative/io/timer_unix.rs b/src/libnative/io/timer_unix.rs
index 11f9c4b3d8c..ca0a810890c 100644
--- a/src/libnative/io/timer_unix.rs
+++ b/src/libnative/io/timer_unix.rs
@@ -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 helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
 
 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) };
diff --git a/src/librustc/back/arm.rs b/src/librustc/back/arm.rs
index e5e8126ace1..7a944fd5abe 100644
--- a/src/librustc/back/arm.rs
+++ b/src/librustc/back/arm.rs
@@ -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\
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 55998f254ed..ab4eda33d75 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -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 @@ pub mod write {
                 } 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 {
diff --git a/src/librustc/back/mips.rs b/src/librustc/back/mips.rs
index 9f640a2c9cb..ea9879dbf49 100644
--- a/src/librustc/back/mips.rs
+++ b/src/librustc/back/mips.rs
@@ -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\
diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs
index cdf49304f9a..a458cf22a5b 100644
--- a/src/librustc/back/rpath.rs
+++ b/src/librustc/back/rpath.rs
@@ -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();
diff --git a/src/librustc/back/x86.rs b/src/librustc/back/x86.rs
index 3ef013d47c9..90106e9e030 100644
--- a/src/librustc/back/x86.rs
+++ b/src/librustc/back/x86.rs
@@ -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()
           }
diff --git a/src/librustc/back/x86_64.rs b/src/librustc/back/x86_64.rs
index 80dd2b2c516..55b0eca7be7 100644
--- a/src/librustc/back/x86_64.rs
+++ b/src/librustc/back/x86_64.rs
@@ -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-\
diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs
index 186db839e33..2f7dc136ef2 100644
--- a/src/librustc/driver/config.rs
+++ b/src/librustc/driver/config.rs
@@ -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 @@ static os_names : &'static [(&'static str, abi::Os)] = &'static [
     ("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() {
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index 773b9e6e0aa..bc22b3ca7e2 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -249,4 +249,3 @@ pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> String)
               -> T {
     diagnostic::expect(sess.diagnostic(), opt, msg)
 }
-
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 4df21fbc974..63b177b0eb7 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -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")) {
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index cfda97ad26f..a674b6cf5a9 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -39,6 +39,9 @@ use time;
 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 @@ impl<'a> Context<'a> {
             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",
diff --git a/src/librustc/middle/trans/cabi_x86.rs b/src/librustc/middle/trans/cabi_x86.rs
index 93b6fdd8988..d10f6b72820 100644
--- a/src/librustc/middle/trans/cabi_x86.rs
+++ b/src/librustc/middle/trans/cabi_x86.rs
@@ -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)),
diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs
index b28db3d378b..24f30bae75a 100644
--- a/src/librustc/middle/trans/cleanup.rs
+++ b/src/librustc/middle/trans/cleanup.rs
@@ -680,7 +680,7 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> {
                     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());
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index db17000abb3..c50badac531 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -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 {
diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs
index 8ad10a686e6..800e7f065f1 100644
--- a/src/librustdoc/flock.rs
+++ b/src/librustdoc/flock.rs
@@ -64,6 +64,7 @@ mod imp {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     mod os {
         use libc;
 
diff --git a/src/librustrt/args.rs b/src/librustrt/args.rs
index 0789bf7f906..d6d4b18051b 100644
--- a/src/librustrt/args.rs
+++ b/src/librustrt/args.rs
@@ -145,6 +145,7 @@ mod imp {
 }
 
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 #[cfg(target_os = "win32")]
 mod imp {
     use core::prelude::*;
diff --git a/src/librustrt/lib.rs b/src/librustrt/lib.rs
index 76cbeef443e..e17a43322ba 100644
--- a/src/librustrt/lib.rs
+++ b/src/librustrt/lib.rs
@@ -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;
 }
 
diff --git a/src/librustrt/libunwind.rs b/src/librustrt/libunwind.rs
index 846ec248805..50c2aba2b5c 100644
--- a/src/librustrt/libunwind.rs
+++ b/src/librustrt/libunwind.rs
@@ -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 static unwinder_private_data_size: int = 5;
 #[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 @@ extern {}
 #[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)
+}
diff --git a/src/librustrt/local_ptr.rs b/src/librustrt/local_ptr.rs
index 91e3409892e..b6858be32b7 100644
--- a/src/librustrt/local_ptr.rs
+++ b/src/librustrt/local_ptr.rs
@@ -24,10 +24,11 @@ use alloc::owned::Box;
 
 #[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::*;
 
diff --git a/src/librustrt/mutex.rs b/src/librustrt/mutex.rs
index eec19e9d5db..26359ff7f6e 100644
--- a/src/librustrt/mutex.rs
+++ b/src/librustrt/mutex.rs
@@ -283,6 +283,7 @@ mod imp {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     mod os {
         use libc;
 
@@ -294,6 +295,10 @@ mod imp {
         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;
diff --git a/src/librustrt/stack.rs b/src/librustrt/stack.rs
index aac773f6f85..e6fa845bedc 100644
--- a/src/librustrt/stack.rs
+++ b/src/librustrt/stack.rs
@@ -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 @@ pub unsafe fn 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 @@ pub unsafe fn 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
diff --git a/src/librustrt/thread.rs b/src/librustrt/thread.rs
index 4ef2cec19db..3dcd1c4a6f0 100644
--- a/src/librustrt/thread.rs
+++ b/src/librustrt/thread.rs
@@ -276,7 +276,6 @@ mod imp {
     }
 
     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 @@ mod tests {
         assert_eq!(42, Thread::start_stack(1, proc () 42).join());
     }
 }
-
diff --git a/src/librustrt/thread_local_storage.rs b/src/librustrt/thread_local_storage.rs
index 2cdeb21fb83..4a7be39e6b8 100644
--- a/src/librustrt/thread_local_storage.rs
+++ b/src/librustrt/thread_local_storage.rs
@@ -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;
 
diff --git a/src/librustrt/unwind.rs b/src/librustrt/unwind.rs
index f7475db1552..e60c50f0adb 100644
--- a/src/librustrt/unwind.rs
+++ b/src/librustrt/unwind.rs
@@ -285,16 +285,74 @@ pub mod eabi {
         }
         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 mod eabi {
         }
         else { // cleanup phase
             unsafe {
-                 __gcc_personality_v0(state, ue_header, context)
+                __gcc_personality_v0(state, ue_header, context)
             }
         }
     }
diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs
index fa6efc8a4b1..5dbed6844c3 100644
--- a/src/libstd/dynamic_lib.rs
+++ b/src/libstd/dynamic_lib.rs
@@ -153,7 +153,7 @@ impl DynamicLibrary {
     }
 }
 
-#[cfg(test)]
+#[cfg(test, not(target_os = "ios"))]
 mod test {
     use super::*;
     use prelude::*;
@@ -205,6 +205,7 @@ mod test {
 #[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::*;
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index cc76cde7baf..f6b1c04dd34 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -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 @@ pub fn self_exe_name() -> Option<Path> {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     fn load_self() -> Option<Vec<u8>> {
         unsafe {
             use libc::funcs::extra::_NSGetExecutablePath;
@@ -802,6 +804,7 @@ pub fn change_dir(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;
diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs
index 2654b7a1acc..f507011c2b9 100644
--- a/src/libstd/rand/os.rs
+++ b/src/libstd/rand/os.rs
@@ -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 @@ mod imp {
     }
 }
 
+#[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;
diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs
index a1372b51d47..16b598b3ae7 100644
--- a/src/libstd/rt/backtrace.rs
+++ b/src/libstd/rt/backtrace.rs
@@ -237,22 +237,58 @@ fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> {
 #[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 @@ mod imp {
             // 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 @@ mod imp {
     }
 
     #[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 @@ mod imp {
         }
     }
 
-    #[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 @@ mod imp {
 
     /// 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 @@ mod imp {
                           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;
diff --git a/src/libstd/rtdeps.rs b/src/libstd/rtdeps.rs
index c804918ae4b..f8bfde52261 100644
--- a/src/libstd/rtdeps.rs
+++ b/src/libstd/rtdeps.rs
@@ -39,3 +39,7 @@ extern {}
 #[cfg(target_os = "macos")]
 #[link(name = "System")]
 extern {}
+
+#[cfg(target_os = "ios")]
+#[link(name = "System")]
+extern {}
diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs
index cfe85995df6..ec54a033e71 100644
--- a/src/libsyntax/abi.rs
+++ b/src/libsyntax/abi.rs
@@ -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 {
diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs
index 63523cd3a6f..b4a2e92cc12 100644
--- a/src/libtime/lib.rs
+++ b/src/libtime/lib.rs
@@ -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 @@ pub fn get_time() -> Timespec {
     }
 
     #[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 @@ pub fn get_time() -> Timespec {
         (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 @@ pub fn 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 @@ pub fn 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 {