about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-06-16 06:32:03 +0000
committerbors <bors@rust-lang.org>2014-06-16 06:32:03 +0000
commit2ef910f71ab83761b1f5f9144621f246622e92d8 (patch)
tree260c5393432cab41234c55eb88f24575afa2ad16
parent6d8342f5e9f7093694548e761ee7df4f55243f3f (diff)
parent2ec323e4c30c265f35314c0a77f5df5a655cec2f (diff)
downloadrust-2ef910f71ab83761b1f5f9144621f246622e92d8.tar.gz
rust-2ef910f71ab83761b1f5f9144621f246622e92d8.zip
auto merge of #14715 : vhbit/rust/ios-pr2, r=alexcrichton
-rw-r--r--mk/platform.mk96
-rw-r--r--mk/rt.mk48
m---------src/compiler-rt0
m---------src/jemalloc0
-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.rs13
-rw-r--r--src/librustc/back/link.rs70
-rw-r--r--src/librustc/back/mips.rs13
-rw-r--r--src/librustc/back/rpath.rs2
-rw-r--r--src/librustc/back/target_strs.rs1
-rw-r--r--src/librustc/back/x86.rs13
-rw-r--r--src/librustc/back/x86_64.rs11
-rw-r--r--src/librustc/driver/config.rs28
-rw-r--r--src/librustc/driver/driver.rs19
-rw-r--r--src/librustc/driver/mod.rs3
-rw-r--r--src/librustc/driver/session.rs1
-rw-r--r--src/librustc/metadata/creader.rs9
-rw-r--r--src/librustc/metadata/loader.rs74
-rw-r--r--src/librustc/middle/trans/base.rs31
-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/context.rs20
-rw-r--r--src/librustc/middle/trans/debuginfo.rs3
-rw-r--r--src/librustc/middle/trans/glue.rs2
-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.rs27
-rw-r--r--src/librustrt/local_ptr.rs5
-rw-r--r--src/librustrt/mutex.rs5
-rw-r--r--src/librustrt/stack.rs51
-rw-r--r--src/librustrt/thread.rs2
-rw-r--r--src/librustrt/thread_local_storage.rs3
-rw-r--r--src/librustrt/unwind.rs63
-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.rs65
-rw-r--r--src/libstd/rtdeps.rs4
-rw-r--r--src/libsyntax/abi.rs15
-rw-r--r--src/libtime/lib.rs9
-rw-r--r--src/rt/arch/arm/_context.S24
-rw-r--r--src/rt/arch/arm/morestack.S62
-rw-r--r--src/rt/arch/arm/record_sp.S26
50 files changed, 801 insertions, 227 deletions
diff --git a/mk/platform.mk b/mk/platform.mk
index 3ab55ce4b7b..1efa1cc5b6d 100644
--- a/mk/platform.mk
+++ b/mk/platform.mk
@@ -155,36 +155,76 @@ CFG_LDPATH_i686-unknown-linux-gnu :=
 CFG_RUN_i686-unknown-linux-gnu=$(2)
 CFG_RUN_TARG_i686-unknown-linux-gnu=$(call CFG_RUN_i686-unknown-linux-gnu,,$(2))
 
-# arm-apple-darwin configuration
-ifeq ($(CFG_OSTYPE),apple-darwin)
+# arm-apple-ios configuration
+CFG_SDK_NAME_arm-apple-ios = iphoneos
+CFG_SDK_ARCHS_arm-apple-ios = armv7
+ifneq ($(findstring darwin,$(CFG_OSTYPE)),)
 CFG_IOS_SDK = $(shell xcrun --show-sdk-path -sdk iphoneos 2>/dev/null)
-CFG_IOS_FLAGS = -target arm-apple-darwin -isysroot $(CFG_IOS_SDK) -I$(CFG_IOS_SDK)/usr/include -I$(CFG_IOS_SDK)/usr/include/c++/4.2.1
-CC_arm-apple-darwin = $(shell xcrun -find -sdk iphoneos clang)
-CXX_arm-apple-darwin = $(shell xcrun -find -sdk iphoneos clang++)
-CPP_arm-apple-darwin = $(shell xcrun -find -sdk iphoneos clang++)
-AR_arm-apple-darwin = $(shell xcrun -find -sdk iphoneos ar)
-CFG_LIB_NAME_arm-apple-darwin = lib$(1).dylib
-CFG_LIB_GLOB_arm-apple-darwin = lib$(1)-*.dylib
-CFG_LIB_DSYM_GLOB_arm-apple-darwin = lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-apple-darwin := $(CFG_IOS_FLAGS) $(CFLAGS)
-CFG_GCCISH_CFLAGS_arm-apple-darwin := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS) $(CFLAGS)
-CFG_GCCISH_CXXFLAGS_arm-apple-darwin := -fno-rtti $(CFG_IOS_FLAGS) $(CXXFLAGS)
-CFG_GCCISH_LINK_FLAGS_arm-apple-darwin := -dynamiclib -lpthread -framework CoreServices -Wl,-no_compact_unwind
-CFG_GCCISH_DEF_FLAG_arm-apple-darwin := -Wl,-exported_symbols_list,
-CFG_GCCISH_PRE_LIB_FLAGS_arm-apple-darwin :=
-CFG_GCCISH_POST_LIB_FLAGS_arm-apple-darwin :=
-CFG_DEF_SUFFIX_arm-apple-darwin := .darwin.def
-CFG_LLC_FLAGS_arm-apple-darwin :=
-CFG_INSTALL_NAME_arm-apple-darwin = -Wl,-install_name,@rpath/$(1)
-CFG_LIBUV_LINK_FLAGS_arm-apple-darwin =
-CFG_EXE_SUFFIX_arm-apple-darwin :=
-CFG_WINDOWSY_arm-apple-darwin :=
-CFG_UNIXY_arm-apple-darwin := 1
-CFG_PATH_MUNGE_arm-apple-darwin := true
-CFG_LDPATH_arm-apple-darwin :=
-CFG_RUN_arm-apple-darwin = $(2)
-CFG_RUN_TARG_arm-apple-darwin = $(call CFG_RUN_arm-apple-darwin,,$(2))
+CFG_IOS_FLAGS = -target armv7-apple-darwin -isysroot $(CFG_IOS_SDK) -mios-version-min=7.0
+CC_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang)
+CXX_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang++)
+CPP_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang++)
+AR_arm-apple-ios = $(shell xcrun -find -sdk iphoneos ar)
 endif
+CFG_LIB_NAME_arm-apple-ios = lib$(1).a
+CFG_LIB_GLOB_arm-apple-ios = lib$(1)-*.a
+CFG_STATIC_LIB_NAME_arm-apple-ios=lib$(1).a
+CFG_LIB_DSYM_GLOB_arm-apple-ios = lib$(1)-*.a.dSYM
+CFG_CFLAGS_arm-apple-ios := -arch armv7 -mfpu=vfp3 $(CFG_IOS_FLAGS)
+CFG_GCCISH_CFLAGS_arm-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS) -mfpu=vfp3 -arch armv7
+CFG_GCCISH_CXXFLAGS_arm-apple-ios := -fno-rtti $(CFG_IOS_FLAGS) -I$(CFG_IOS_SDK)/usr/include/c++/4.2.1
+CFG_GCCISH_LINK_FLAGS_arm-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK) -Wl,-no_compact_unwind
+CFG_GCCISH_DEF_FLAG_arm-apple-ios := -Wl,-exported_symbols_list,
+CFG_GCCISH_PRE_LIB_FLAGS_arm-apple-ios :=
+CFG_GCCISH_POST_LIB_FLAGS_arm-apple-ios :=
+CFG_DEF_SUFFIX_arm-apple-ios := .darwin.def
+CFG_LLC_FLAGS_arm-apple-ios := -mattr=+vfp3,+v7,+thumb2,+neon -march=arm
+CFG_INSTALL_NAME_arm-apple-ios = -Wl,-install_name,@rpath/$(1)
+CFG_LIBUV_LINK_FLAGS_arm-apple-ios =
+CFG_EXE_SUFFIX_arm-apple-ios :=
+CFG_WINDOWSY_arm-apple-ios :=
+CFG_UNIXY_arm-apple-ios := 1
+CFG_PATH_MUNGE_arm-apple-ios := true
+CFG_LDPATH_arm-apple-ios :=
+CFG_RUN_arm-apple-ios = $(2)
+CFG_RUN_TARG_arm-apple-ios = $(call CFG_RUN_arm-apple-ios,,$(2))
+RUSTC_FLAGS_arm-apple-ios := -C relocation_model=pic
+RUSTC_CROSS_FLAGS_arm-apple-ios :=-C relocation_model=pic
+
+# i386-apple-ios configuration
+CFG_SDK_NAME_i386-apple-ios = iphonesimulator
+CFG_SDK_ARCHS_i386-apple-ios = i386
+ifneq ($(findstring darwin,$(CFG_OSTYPE)),)
+CFG_IOSSIM_SDK = $(shell xcrun --show-sdk-path -sdk iphonesimulator 2>/dev/null)
+CFG_IOSSIM_FLAGS = -target i386-apple-ios -isysroot $(CFG_IOSSIM_SDK) -mios-simulator-version-min=7.0
+CC_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator clang)
+CXX_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator clang++)
+CPP_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator clang++)
+AR_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator ar)
+endif
+CFG_LIB_NAME_i386-apple-ios = lib$(1).a
+CFG_LIB_GLOB_i386-apple-ios = lib$(1)-*.dylib
+CFG_STATIC_LIB_NAME_i386-apple-ios=lib$(1).a
+CFG_LIB_DSYM_GLOB_i386-apple-ios = lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_i386-apple-ios = $(CFG_IOSSIM_FLAGS)
+CFG_GCCISH_CFLAGS_i386-apple-ios = -Wall -Werror -g -fPIC -m32 $(CFG_IOSSIM_FLAGS)
+CFG_GCCISH_CXXFLAGS_i386-apple-ios = -fno-rtti $(CFG_IOSSIM_FLAGS) -I$(CFG_IOSSIM_SDK)/usr/include/c++/4.2.1
+CFG_GCCISH_LINK_FLAGS_i386-apple-ios = -lpthread -Wl,-no_compact_unwind -m32 -Wl,-syslibroot $(CFG_IOSSIM_SDK)
+CFG_GCCISH_DEF_FLAG_i386-apple-ios = -Wl,-exported_symbols_list,
+CFG_GCCISH_PRE_LIB_FLAGS_i386-apple-ios =
+CFG_GCCISH_POST_LIB_FLAGS_i386-apple-ios =
+CFG_DEF_SUFFIX_i386-apple-ios = .darwin.def
+CFG_LLC_FLAGS_i386-apple-ios =
+CFG_INSTALL_NAME_i386-apple-ios = -Wl,-install_name,@rpath/$(1)
+CFG_LIBUV_LINK_FLAGS_i386-apple-ios =
+CFG_EXE_SUFFIX_i386-apple-ios =
+CFG_WINDOWSY_i386-apple-ios =
+CFG_UNIXY_i386-apple-ios = 1
+CFG_PATH_MUNGE_i386-apple-ios = true
+CFG_LDPATH_i386-apple-ios =
+CFG_RUN_i386-apple-ios = $(2)
+CFG_RUN_TARG_i386-apple-ios = $(call CFG_RUN_i386-apple-ios,,$(2))
+CFG_JEMALLOC_CFLAGS_i386-apple-ios = -target i386-apple-ios -Wl,-syslibroot $(CFG_IOSSIM_SDK) -Wl,-no_compact_unwind
 
 # x86_64-apple-darwin configuration
 CC_x86_64-apple-darwin=$(CC)
diff --git a/mk/rt.mk b/mk/rt.mk
index 1c4efd641f0..7fc82ef6269 100644
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -166,6 +166,9 @@ ifeq ($$(CFG_WINDOWSY_$(1)), 1)
   JEMALLOC_ARGS_$(1) := --enable-lazy-lock
 else ifeq ($(OSTYPE_$(1)), apple-darwin)
   LIBUV_OSTYPE_$(1) := mac
+else ifeq ($(OSTYPE_$(1)), apple-ios)
+  LIBUV_OSTYPE_$(1) := ios
+  JEMALLOC_ARGS_$(1) := --disable-tls
 else ifeq ($(OSTYPE_$(1)), unknown-freebsd)
   LIBUV_OSTYPE_$(1) := freebsd
 else ifeq ($(OSTYPE_$(1)), linux-androideabi)
@@ -181,6 +184,8 @@ LIBUV_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/libuv
 LIBUV_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(LIBUV_NAME_$(1))
 
 LIBUV_MAKEFILE_$(1) := $$(CFG_BUILD_DIR)$$(RT_OUTPUT_DIR_$(1))/libuv/Makefile
+LIBUV_BUILD_DIR_$(1) := $$(CFG_BUILD_DIR)$$(RT_OUTPUT_DIR_$(1))/libuv
+LIBUV_XCODEPROJ_$(1) := $$(LIBUV_BUILD_DIR_$(1))/uv.xcodeproj
 
 LIBUV_STAMP_$(1) = $$(LIBUV_DIR_$(1))/libuv-auto-clean-stamp
 
@@ -212,6 +217,30 @@ $$(LIBUV_LOCAL_$(1)): $$(LIBUV_DEPS) $$(MKFILE_DEPS)
 		CXX="$$(CXX_$(1))" \
 		AR="$$(AR_$(1))" \
 		V=$$(VERBOSE)
+else ifeq ($(OSTYPE_$(1)), apple-ios) # iOS
+$$(LIBUV_XCODEPROJ_$(1)): $$(LIBUV_DEPS) $$(MKFILE_DEPS) $$(LIBUV_STAMP_$(1))
+	cp -rf $(S)src/libuv/ $$(LIBUV_BUILD_DIR_$(1))
+	(cd $$(LIBUV_BUILD_DIR_$(1)) && \
+	 $$(CFG_PYTHON) ./gyp_uv.py -f xcode \
+	   -D ninja \
+	   -R libuv)
+	touch $$@
+
+LIBUV_XCODE_OUT_LIB_$(1) := $$(LIBUV_BUILD_DIR_$(1))/build/Release-$$(CFG_SDK_NAME_$(1))/libuv.a
+
+$$(LIBUV_LIB_$(1)): $$(LIBUV_XCODE_OUT_LIB_$(1)) $$(MKFILE_DEPS)
+	$$(Q)cp $$< $$@
+$$(LIBUV_XCODE_OUT_LIB_$(1)): $$(LIBUV_DEPS) $$(LIBUV_XCODEPROJ_$(1)) \
+				    $$(MKFILE_DEPS)
+	$$(Q)xcodebuild -project $$(LIBUV_BUILD_DIR_$(1))/uv.xcodeproj \
+		CFLAGS="$$(LIBUV_CFLAGS_$(1)) $$(SNAP_DEFINES)" \
+		LDFLAGS="$$(CFG_GCCISH_LINK_FLAGS_$(1))" \
+		$$(LIBUV_ARGS_$(1)) \
+		V=$$(VERBOSE) \
+		-configuration Release \
+		-sdk "$$(CFG_SDK_NAME_$(1))" \
+		ARCHS="$$(CFG_SDK_ARCHS_$(1))"
+	$$(Q)touch $$@
 else
 LIBUV_LOCAL_$(1) := $$(LIBUV_DIR_$(1))/Release/libuv.a
 $$(LIBUV_LOCAL_$(1)): $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)) $$(MKFILE_DEPS)
@@ -226,7 +255,6 @@ $$(LIBUV_LOCAL_$(1)): $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)) $$(MKFILE_DEPS)
 		NO_LOAD="$$(LIBUV_NO_LOAD)" \
 		V=$$(VERBOSE)
 	$$(Q)touch $$@
-
 endif
 
 ifeq ($(1),$$(CFG_BUILD))
@@ -269,13 +297,13 @@ JEMALLOC_LOCAL_$(1) := $$(JEMALLOC_BUILD_DIR_$(1))/lib/$$(JEMALLOC_REAL_NAME_$(1
 $$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
 	@$$(call E, make: jemalloc)
 	cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \
-		$$(JEMALLOC_ARGS_$(1)) --enable-cc-silence --with-jemalloc-prefix=je_ \
-		--disable-experimental --build=$(CFG_BUILD) --host=$(1) \
+		$$(JEMALLOC_ARGS_$(1)) --with-jemalloc-prefix=je_ \
+		--build=$(CFG_BUILD) --host=$(1) \
 		CC="$$(CC_$(1))" \
 		AR="$$(AR_$(1))" \
 		RANLIB="$$(AR_$(1)) s" \
 		CPPFLAGS="-I $(S)src/rt/" \
-		EXTRA_CFLAGS="$$(CFG_CFLAGS_$(1)) -g1"
+		EXTRA_CFLAGS="$$(CFG_CFLAGS_$(1)) $$(CFG_JEMALLOC_CFLAGS_$(1)) -g1"
 	$$(Q)$$(MAKE) -C "$$(JEMALLOC_BUILD_DIR_$(1))" build_lib_static
 
 ifeq ($(1),$$(CFG_BUILD))
@@ -335,15 +363,22 @@ BACKTRACE_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),backtrace)
 BACKTRACE_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(BACKTRACE_NAME_$(1))
 BACKTRACE_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/libbacktrace
 
-ifeq ($$(findstring darwin,$$(OSTYPE_$(1))),darwin)
-
 # We don't use this on platforms that aren't linux-based, so just make the file
 # available, the compilation of libstd won't actually build it.
+ifeq ($$(findstring darwin,$$(OSTYPE_$(1))),darwin)
+# See comment above
 $$(BACKTRACE_LIB_$(1)):
 	touch $$@
 
 else
+ifeq ($$(findstring ios,$$(OSTYPE_$(1))),ios)
+# See comment above
+$$(BACKTRACE_LIB_$(1)):
+	touch $$@
+else
+
 ifeq ($$(CFG_WINDOWSY_$(1)),1)
+# See comment above
 $$(BACKTRACE_LIB_$(1)):
 	touch $$@
 else
@@ -388,6 +423,7 @@ $$(BACKTRACE_LIB_$(1)): $$(BACKTRACE_BUILD_DIR_$(1))/Makefile $$(MKFILE_DEPS)
 	$$(Q)cp $$(BACKTRACE_BUILD_DIR_$(1))/.libs/libbacktrace.a $$@
 
 endif # endif for windowsy
+endif # endif for ios
 endif # endif for darwin
 
 endef
diff --git a/src/compiler-rt b/src/compiler-rt
-Subproject ed112ca1e4275e1c5707a898f2bf6164707ba37
+Subproject 7b97b8468f0614072cf3299fa8c51e85f609316
diff --git a/src/jemalloc b/src/jemalloc
-Subproject 6a96910f2eaea6d2c705bb12379b23576b30d7d
+Subproject 024c67ad651e1a3ca228936c4cfb13a37329baf
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 1c33114dc71..2694c932b95 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..7a7d248a4cb 100644
--- a/src/librustc/back/arm.rs
+++ b/src/librustc/back/arm.rs
@@ -9,8 +9,6 @@
 // except according to those terms.
 
 use back::target_strs;
-use driver::config::cfg_os_to_meta_os;
-use metadata::loader::meta_section_name;
 use syntax::abi;
 
 pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs::t {
@@ -22,9 +20,6 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
     return target_strs::t {
         module_asm: "".to_string(),
 
-        meta_sect_name:
-            meta_section_name(cfg_os_to_meta_os(target_os)).to_string(),
-
         data_layout: match target_os {
           abi::OsMacos => {
             "e-p:32:32:32\
@@ -34,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/link.rs b/src/librustc/back/link.rs
index 55998f254ed..d644a0cc353 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()
         }
     }
@@ -796,6 +806,10 @@ pub fn link_binary(sess: &Session,
                    id: &CrateId) -> Vec<Path> {
     let mut out_filenames = Vec::new();
     for &crate_type in sess.crate_types.borrow().iter() {
+        if invalid_output_for_target(sess, crate_type) {
+            sess.bug(format!("invalid output type `{}` for target os `{}`",
+                             crate_type, sess.targ_cfg.os).as_slice());
+        }
         let out_file = link_binary_output(sess, trans, crate_type, outputs, id);
         out_filenames.push(out_file);
     }
@@ -812,6 +826,32 @@ pub fn link_binary(sess: &Session,
     out_filenames
 }
 
+
+/// Returns default crate type for target
+///
+/// Default crate type is used when crate type isn't provided neither
+/// through cmd line arguments nor through crate attributes
+///
+/// It is CrateTypeExecutable for all platforms but iOS as there is no
+/// way to run iOS binaries anyway without jailbreaking and
+/// interaction with Rust code through static library is the only
+/// option for now
+pub fn default_output_for_target(sess: &Session) -> config::CrateType {
+    match sess.targ_cfg.os {
+        abi::OsiOS => config::CrateTypeStaticlib,
+        _ => config::CrateTypeExecutable
+    }
+}
+
+/// Checks if target supports crate_type as output
+pub fn invalid_output_for_target(sess: &Session,
+                                 crate_type: config::CrateType) -> bool {
+    match (sess.targ_cfg.os, crate_type) {
+        (abi::OsiOS, config::CrateTypeDylib) => true,
+        _ => false
+    }
+}
+
 fn is_writeable(p: &Path) -> bool {
     match p.stat() {
         Err(..) => true,
@@ -833,8 +873,11 @@ pub fn filename_for_input(sess: &Session, crate_type: config::CrateType,
                 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,
+            out_filename.with_filename(format!("{}{}{}",
+                                               prefix,
+                                               libname,
                                                suffix))
         }
         config::CrateTypeStaticlib => {
@@ -991,7 +1034,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 +1147,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 +1213,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 +1229,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 +1392,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..8f3da03e825 100644
--- a/src/librustc/back/mips.rs
+++ b/src/librustc/back/mips.rs
@@ -9,17 +9,12 @@
 // except according to those terms.
 
 use back::target_strs;
-use driver::config::cfg_os_to_meta_os;
-use metadata::loader::meta_section_name;
 use syntax::abi;
 
 pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs::t {
     return target_strs::t {
         module_asm: "".to_string(),
 
-        meta_sect_name:
-            meta_section_name(cfg_os_to_meta_os(target_os)).to_string(),
-
         data_layout: match target_os {
           abi::OsMacos => {
             "E-p:32:32:32\
@@ -29,6 +24,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/target_strs.rs b/src/librustc/back/target_strs.rs
index ed5976ad508..7928f3d8db0 100644
--- a/src/librustc/back/target_strs.rs
+++ b/src/librustc/back/target_strs.rs
@@ -12,7 +12,6 @@
 
 pub struct t {
     pub module_asm: String,
-    pub meta_sect_name: String,
     pub data_layout: String,
     pub target_triple: String,
     pub cc_args: Vec<String> ,
diff --git a/src/librustc/back/x86.rs b/src/librustc/back/x86.rs
index 3ef013d47c9..d2dac03267d 100644
--- a/src/librustc/back/x86.rs
+++ b/src/librustc/back/x86.rs
@@ -10,8 +10,6 @@
 
 
 use back::target_strs;
-use driver::config::cfg_os_to_meta_os;
-use metadata::loader::meta_section_name;
 use syntax::abi;
 
 pub fn get_target_strs(target_triple: String, target_os: abi::Os)
@@ -19,9 +17,6 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os)
     return target_strs::t {
         module_asm: "".to_string(),
 
-        meta_sect_name:
-            meta_section_name(cfg_os_to_meta_os(target_os)).to_string(),
-
         data_layout: match target_os {
           abi::OsMacos => {
             "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\
@@ -31,6 +26,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..c2eae18737b 100644
--- a/src/librustc/back/x86_64.rs
+++ b/src/librustc/back/x86_64.rs
@@ -10,17 +10,12 @@
 
 
 use back::target_strs;
-use driver::config::cfg_os_to_meta_os;
-use metadata::loader::meta_section_name;
 use syntax::abi;
 
 pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs::t {
     return target_strs::t {
         module_asm: "".to_string(),
 
-        meta_sect_name:
-            meta_section_name(cfg_os_to_meta_os(target_os)).to_string(),
-
         data_layout: match target_os {
           abi::OsMacos => {
             "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
@@ -28,6 +23,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 b8838890bcf..db96330d656 100644
--- a/src/librustc/driver/config.rs
+++ b/src/librustc/driver/config.rs
@@ -19,7 +19,6 @@ use back;
 use back::link;
 use back::target_strs;
 use back::{arm, x86, x86_64, mips};
-use metadata;
 use middle::lint;
 
 use syntax::abi;
@@ -36,6 +35,7 @@ use getopts::{optopt, optmulti, optflag, optflagopt};
 use getopts;
 use lib::llvm::llvm;
 use std::cell::{RefCell};
+use std::fmt;
 
 
 pub struct Config {
@@ -357,18 +357,6 @@ pub fn default_lib_output() -> CrateType {
     CrateTypeRlib
 }
 
-pub fn cfg_os_to_meta_os(os: abi::Os) -> metadata::loader::Os {
-    use metadata::loader;
-
-    match os {
-        abi::OsWin32 => loader::OsWin32,
-        abi::OsLinux => loader::OsLinux,
-        abi::OsAndroid => loader::OsAndroid,
-        abi::OsMacos => loader::OsMacos,
-        abi::OsFreebsd => loader::OsFreebsd
-    }
-}
-
 pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
     let tos = match sess.targ_cfg.os {
         abi::OsWin32 =>   InternedString::new("win32"),
@@ -376,6 +364,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
@@ -441,7 +430,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() {
@@ -775,6 +765,16 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     }
 }
 
+impl fmt::Show for CrateType {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            CrateTypeExecutable => "bin".fmt(f),
+            CrateTypeDylib => "dylib".fmt(f),
+            CrateTypeRlib => "rlib".fmt(f),
+            CrateTypeStaticlib => "staticlib".fmt(f)
+        }
+    }
+}
 
 #[cfg(test)]
 mod test {
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 2268ce84365..e767a7c84f6 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -794,17 +794,26 @@ pub fn collect_crate_types(session: &Session,
     // command line, then reuse the empty `base` Vec to hold the types that
     // will be found in crate attributes.
     let mut base = session.opts.crate_types.clone();
-    if base.len() > 0 {
-        return base
-    } else {
+    if base.len() == 0 {
         base.extend(attr_types.move_iter());
         if base.len() == 0 {
-            base.push(config::CrateTypeExecutable);
+            base.push(link::default_output_for_target(session));
         }
         base.as_mut_slice().sort();
         base.dedup();
-        return base;
     }
+
+    base.move_iter().filter(|crate_type| {
+        let res = !link::invalid_output_for_target(session, *crate_type);
+
+        if !res {
+            session.warn(format!("dropping unsupported crate type `{}` \
+                                   for target os `{}`",
+                                 *crate_type, session.targ_cfg.os).as_slice());
+        }
+
+        res
+    }).collect()
 }
 
 pub struct OutputFilenames {
diff --git a/src/librustc/driver/mod.rs b/src/librustc/driver/mod.rs
index ff7f59559ca..ada65394e19 100644
--- a/src/librustc/driver/mod.rs
+++ b/src/librustc/driver/mod.rs
@@ -349,8 +349,7 @@ pub fn early_error(msg: &str) -> ! {
 
 pub fn list_metadata(sess: &Session, path: &Path,
                      out: &mut io::Writer) -> io::IoResult<()> {
-    metadata::loader::list_file_metadata(
-        config::cfg_os_to_meta_os(sess.targ_cfg.os), path, out)
+    metadata::loader::list_file_metadata(sess.targ_cfg.os, path, out)
 }
 
 /// Run a procedure which will detect failures in the compiler and print nicer
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index 3efff5eac9e..f98831714f2 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -250,4 +250,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..efe28614b8f 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")) {
@@ -345,7 +346,7 @@ fn resolve_crate<'a>(e: &mut Env,
                 id_hash: id_hash.as_slice(),
                 hash: hash.map(|a| &*a),
                 filesearch: e.sess.target_filesearch(),
-                os: config::cfg_os_to_meta_os(e.sess.targ_cfg.os),
+                os: e.sess.targ_cfg.os,
                 triple: e.sess.targ_cfg.target_strs.target_triple.as_slice(),
                 root: root,
                 rejected_via_hash: vec!(),
@@ -409,7 +410,7 @@ impl<'a> PluginMetadataReader<'a> {
             hash: None,
             filesearch: self.env.sess.host_filesearch(),
             triple: driver::host_triple(),
-            os: config::cfg_os_to_meta_os(os),
+            os: os,
             root: &None,
             rejected_via_hash: vec!(),
             rejected_via_triple: vec!(),
@@ -420,7 +421,7 @@ impl<'a> PluginMetadataReader<'a> {
                 // try loading from target crates (only valid if there are
                 // no syntax extensions)
                 load_ctxt.triple = target_triple;
-                load_ctxt.os = config::cfg_os_to_meta_os(self.env.sess.targ_cfg.os);
+                load_ctxt.os = self.env.sess.targ_cfg.os;
                 load_ctxt.filesearch = self.env.sess.target_filesearch();
                 let lib = load_ctxt.load_library_crate();
                 if decoder::get_plugin_registrar_fn(lib.metadata.as_slice()).is_some() {
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index 9e0bea75186..f379302e929 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -18,6 +18,7 @@ use metadata::cstore::{MetadataBlob, MetadataVec, MetadataArchive};
 use metadata::decoder;
 use metadata::encoder;
 use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
+use syntax::abi;
 use syntax::codemap::Span;
 use syntax::diagnostic::SpanHandler;
 use syntax::crateid::CrateId;
@@ -51,14 +52,6 @@ pub static FREEBSD_DLL_SUFFIX: &'static str = ".so";
 pub static ANDROID_DLL_PREFIX: &'static str = "lib";
 pub static ANDROID_DLL_SUFFIX: &'static str = ".so";
 
-pub enum Os {
-    OsMacos,
-    OsWin32,
-    OsLinux,
-    OsAndroid,
-    OsFreebsd
-}
-
 pub struct CrateMismatch {
     path: Path,
     got: String,
@@ -72,7 +65,7 @@ pub struct Context<'a> {
     pub id_hash: &'a str,
     pub hash: Option<&'a Svh>,
     pub triple: &'a str,
-    pub os: Os,
+    pub os: abi::Os,
     pub filesearch: FileSearch<'a>,
     pub root: &'a Option<CratePaths>,
     pub rejected_via_hash: Vec<CrateMismatch>,
@@ -183,10 +176,12 @@ impl<'a> Context<'a> {
     }
 
     fn find_library_crate(&mut self) -> Option<Library> {
-        let (dyprefix, dysuffix) = self.dylibname();
+        let dypair = self.dylibname();
 
         // want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
-        let dylib_prefix = format!("{}{}-", dyprefix, self.crate_id.name);
+        let dylib_prefix = dypair.map(|(prefix, _)| {
+            format!("{}{}-", prefix, self.crate_id.name)
+        });
         let rlib_prefix = format!("lib{}-", self.crate_id.name);
 
         let mut candidates = HashMap::new();
@@ -227,12 +222,14 @@ impl<'a> Context<'a> {
                         FileDoesntMatch
                     }
                 }
-            } else if file.starts_with(dylib_prefix.as_slice()) &&
-                    file.ends_with(dysuffix){
+            } else if dypair.map_or(false, |(_, suffix)| {
+                file.starts_with(dylib_prefix.get_ref().as_slice()) &&
+                file.ends_with(suffix)
+            }) {
+                let (_, suffix) = dypair.unwrap();
+                let dylib_prefix = dylib_prefix.get_ref().as_slice();
                 info!("dylib candidate: {}", path.display());
-                match self.try_match(file,
-                                     dylib_prefix.as_slice(),
-                                     dysuffix) {
+                match self.try_match(file, dylib_prefix, suffix) {
                     Some(hash) => {
                         info!("dylib accepted, hash: {}", hash);
                         let slot = candidates.find_or_insert_with(hash, |_| {
@@ -457,13 +454,14 @@ impl<'a> Context<'a> {
 
     // Returns the corresponding (prefix, suffix) that files need to have for
     // dynamic libraries
-    fn dylibname(&self) -> (&'static str, &'static str) {
+    fn dylibname(&self) -> Option<(&'static str, &'static str)> {
         match self.os {
-            OsWin32 => (WIN32_DLL_PREFIX, WIN32_DLL_SUFFIX),
-            OsMacos => (MACOS_DLL_PREFIX, MACOS_DLL_SUFFIX),
-            OsLinux => (LINUX_DLL_PREFIX, LINUX_DLL_SUFFIX),
-            OsAndroid => (ANDROID_DLL_PREFIX, ANDROID_DLL_SUFFIX),
-            OsFreebsd => (FREEBSD_DLL_PREFIX, FREEBSD_DLL_SUFFIX),
+            abi::OsWin32 => Some((WIN32_DLL_PREFIX, WIN32_DLL_SUFFIX)),
+            abi::OsMacos => Some((MACOS_DLL_PREFIX, MACOS_DLL_SUFFIX)),
+            abi::OsLinux => Some((LINUX_DLL_PREFIX, LINUX_DLL_SUFFIX)),
+            abi::OsAndroid => Some((ANDROID_DLL_PREFIX, ANDROID_DLL_SUFFIX)),
+            abi::OsFreebsd => Some((FREEBSD_DLL_PREFIX, FREEBSD_DLL_SUFFIX)),
+            abi::OsiOS => None,
         }
     }
 
@@ -505,7 +503,7 @@ impl ArchiveMetadata {
 }
 
 // Just a small wrapper to time how long reading metadata takes.
-fn get_metadata_section(os: Os, filename: &Path) -> Result<MetadataBlob, String> {
+fn get_metadata_section(os: abi::Os, filename: &Path) -> Result<MetadataBlob, String> {
     let start = time::precise_time_ns();
     let ret = get_metadata_section_imp(os, filename);
     info!("reading {} => {}ms", filename.filename_display(),
@@ -513,7 +511,7 @@ fn get_metadata_section(os: Os, filename: &Path) -> Result<MetadataBlob, String>
     return ret;
 }
 
-fn get_metadata_section_imp(os: Os, filename: &Path) -> Result<MetadataBlob, String> {
+fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result<MetadataBlob, String> {
     if !filename.exists() {
         return Err(format!("no such file: '{}'", filename.display()));
     }
@@ -599,28 +597,30 @@ fn get_metadata_section_imp(os: Os, filename: &Path) -> Result<MetadataBlob, Str
     }
 }
 
-pub fn meta_section_name(os: Os) -> &'static str {
+pub fn meta_section_name(os: abi::Os) -> Option<&'static str> {
     match os {
-        OsMacos => "__DATA,__note.rustc",
-        OsWin32 => ".note.rustc",
-        OsLinux => ".note.rustc",
-        OsAndroid => ".note.rustc",
-        OsFreebsd => ".note.rustc"
+        abi::OsMacos => Some("__DATA,__note.rustc"),
+        abi::OsiOS => Some("__DATA,__note.rustc"),
+        abi::OsWin32 => Some(".note.rustc"),
+        abi::OsLinux => Some(".note.rustc"),
+        abi::OsAndroid => Some(".note.rustc"),
+        abi::OsFreebsd => Some(".note.rustc")
     }
 }
 
-pub fn read_meta_section_name(os: Os) -> &'static str {
+pub fn read_meta_section_name(os: abi::Os) -> &'static str {
     match os {
-        OsMacos => "__note.rustc",
-        OsWin32 => ".note.rustc",
-        OsLinux => ".note.rustc",
-        OsAndroid => ".note.rustc",
-        OsFreebsd => ".note.rustc"
+        abi::OsMacos => "__note.rustc",
+        abi::OsiOS => unreachable!(),
+        abi::OsWin32 => ".note.rustc",
+        abi::OsLinux => ".note.rustc",
+        abi::OsAndroid => ".note.rustc",
+        abi::OsFreebsd => ".note.rustc"
     }
 }
 
 // A diagnostic function for dumping crate metadata to an output stream
-pub fn list_file_metadata(os: Os, path: &Path,
+pub fn list_file_metadata(os: abi::Os, path: &Path,
                           out: &mut io::Writer) -> io::IoResult<()> {
     match get_metadata_section(os, path) {
         Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out),
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 14c8d5454aa..4657c8cd136 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -35,7 +35,7 @@ use driver::driver::{CrateAnalysis, CrateTranslation};
 use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
 use lib::llvm::{llvm, Vector};
 use lib;
-use metadata::{csearch, encoder};
+use metadata::{csearch, encoder, loader};
 use middle::lint;
 use middle::astencode;
 use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
@@ -173,12 +173,12 @@ impl<'a> Drop for StatRecorder<'a> {
 }
 
 // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
-fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv,
+fn decl_fn(ccx: &CrateContext, name: &str, cc: lib::llvm::CallConv,
            ty: Type, output: ty::t) -> ValueRef {
 
     let llfn: ValueRef = name.with_c_str(|buf| {
         unsafe {
-            llvm::LLVMGetOrInsertFunction(llmod, buf, ty.to_ref())
+            llvm::LLVMGetOrInsertFunction(ccx.llmod, buf, ty.to_ref())
         }
     });
 
@@ -197,17 +197,20 @@ fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv,
     lib::llvm::SetFunctionCallConv(llfn, cc);
     // Function addresses in Rust are never significant, allowing functions to be merged.
     lib::llvm::SetUnnamedAddr(llfn, true);
-    set_split_stack(llfn);
+
+    if ccx.is_split_stack_supported() {
+        set_split_stack(llfn);
+    }
 
     llfn
 }
 
 // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
-pub fn decl_cdecl_fn(llmod: ModuleRef,
+pub fn decl_cdecl_fn(ccx: &CrateContext,
                      name: &str,
                      ty: Type,
                      output: ty::t) -> ValueRef {
-    decl_fn(llmod, name, lib::llvm::CCallConv, ty, output)
+    decl_fn(ccx, name, lib::llvm::CCallConv, ty, output)
 }
 
 // only use this for foreign function ABIs and glue, use `get_extern_rust_fn` for Rust functions
@@ -222,7 +225,7 @@ pub fn get_extern_fn(ccx: &CrateContext,
         Some(n) => return *n,
         None => {}
     }
-    let f = decl_fn(ccx.llmod, name, cc, ty, output);
+    let f = decl_fn(ccx, name, cc, ty, output);
     externs.insert(name.to_string(), f);
     f
 }
@@ -251,7 +254,7 @@ pub fn decl_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str) -> ValueRef {
     };
 
     let llfty = type_of_rust_fn(ccx, has_env, inputs.as_slice(), output);
-    let llfn = decl_fn(ccx.llmod, name, lib::llvm::CCallConv, llfty, output);
+    let llfn = decl_fn(ccx, name, lib::llvm::CCallConv, llfty, output);
     let attrs = get_fn_llvm_attributes(ccx, fn_ty);
     for &(idx, attr) in attrs.iter() {
         unsafe {
@@ -1878,7 +1881,7 @@ pub fn register_fn_llvmty(ccx: &CrateContext,
                           llfty: Type) -> ValueRef {
     debug!("register_fn_llvmty id={} sym={}", node_id, sym);
 
-    let llfn = decl_fn(ccx.llmod, sym.as_slice(), cc, llfty, ty::mk_nil());
+    let llfn = decl_fn(ccx, sym.as_slice(), cc, llfty, ty::mk_nil());
     finish_register_fn(ccx, sp, sym, node_id, llfn);
     llfn
 }
@@ -1910,7 +1913,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
         let llfty = Type::func([ccx.int_type, Type::i8p(ccx).ptr_to()],
                                &ccx.int_type);
 
-        let llfn = decl_cdecl_fn(ccx.llmod, "main", llfty, ty::mk_nil());
+        let llfn = decl_cdecl_fn(ccx, "main", llfty, ty::mk_nil());
         let llbb = "top".with_c_str(|buf| {
             unsafe {
                 llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf)
@@ -2279,12 +2282,8 @@ pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec<u8> {
     });
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
-        cx.sess()
-          .targ_cfg
-          .target_strs
-          .meta_sect_name
-          .as_slice()
-          .with_c_str(|buf| {
+        let name = loader::meta_section_name(cx.sess().targ_cfg.os);
+        name.unwrap_or("rust_metadata").with_c_str(|buf| {
             llvm::LLVMSetSection(llglobal, buf)
         });
     }
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/context.rs b/src/librustc/middle/trans/context.rs
index a80ae9e2596..68c6f1752bd 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 use driver::config::NoDebugInfo;
 use driver::session::Session;
 use lib::llvm::{ContextRef, ModuleRef, ValueRef};
@@ -32,6 +31,7 @@ use std::c_str::ToCStr;
 use std::ptr;
 use std::rc::Rc;
 use std::collections::{HashMap, HashSet};
+use syntax::abi;
 use syntax::ast;
 use syntax::parse::token::InternedString;
 
@@ -273,20 +273,32 @@ impl CrateContext {
             None => fail!()
         }
     }
+
+    // Although there is an experimental implementation of LLVM which
+    // supports SS on armv7 it wasn't approved by Apple, see:
+    // http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140505/216350.html
+    // It looks like it might be never accepted to upstream LLVM.
+    //
+    // So far the decision was to disable them in default builds
+    // but it could be enabled (with patched LLVM)
+    pub fn is_split_stack_supported(&self) -> bool {
+        let ref cfg = self.sess().targ_cfg;
+        cfg.os != abi::OsiOS || cfg.arch != abi::Arm
+    }
 }
 
 fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef> {
     macro_rules! ifn (
         ($name:expr fn() -> $ret:expr) => (
             if *key == $name {
-                let f = base::decl_cdecl_fn(ccx.llmod, $name, Type::func([], &$ret), ty::mk_nil());
+                let f = base::decl_cdecl_fn(ccx, $name, Type::func([], &$ret), ty::mk_nil());
                 ccx.intrinsics.borrow_mut().insert($name, f.clone());
                 return Some(f);
             }
         );
         ($name:expr fn($($arg:expr),*) -> $ret:expr) => (
             if *key == $name {
-                let f = base::decl_cdecl_fn(ccx.llmod, $name,
+                let f = base::decl_cdecl_fn(ccx, $name,
                                   Type::func([$($arg),*], &$ret), ty::mk_nil());
                 ccx.intrinsics.borrow_mut().insert($name, f.clone());
                 return Some(f);
@@ -418,7 +430,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
                 // The `if key == $name` is already in ifn!
                 ifn!($name fn($($arg),*) -> $ret);
             } else if *key == $name {
-                let f = base::decl_cdecl_fn(ccx.llmod, stringify!($cname),
+                let f = base::decl_cdecl_fn(ccx, stringify!($cname),
                                       Type::func([$($arg),*], &$ret),
                                       ty::mk_nil());
                 ccx.intrinsics.borrow_mut().insert($name, f.clone());
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index b5a002fd824..d4efe9b8a09 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -660,7 +660,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/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 96aa7267d23..ef9bf4eebe2 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -462,7 +462,7 @@ fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
         t,
         format!("glue_{}", name).as_slice());
     debug!("{} is for type {}", fn_nm, ppaux::ty_to_str(ccx.tcx(), t));
-    let llfn = decl_cdecl_fn(ccx.llmod, fn_nm.as_slice(), llfnty, ty::mk_nil());
+    let llfn = decl_cdecl_fn(ccx, fn_nm.as_slice(), llfnty, ty::mk_nil());
     note_unique_llvm_symbol(ccx, fn_nm);
     return llfn;
 }
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 6c754178818..c461dccceff 100644
--- a/src/librustrt/lib.rs
+++ b/src/librustrt/lib.rs
@@ -156,7 +156,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..2d58c1bee15 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_...)
+    #[cfg(not(target_os = "ios", target_arch = "arm"))]
     pub fn _Unwind_RaiseException(exception: *_Unwind_Exception)
-                -> _Unwind_Reason_Code;
+                                  -> _Unwind_Reason_Code;
+
+    #[cfg(target_os = "ios", target_arch = "arm")]
+    fn _Unwind_SjLj_RaiseException(e: *_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 {
+    _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 3fece698a1d..ee696f2cf7c 100644
--- a/src/librustrt/mutex.rs
+++ b/src/librustrt/mutex.rs
@@ -361,6 +361,7 @@ mod imp {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     mod os {
         use libc;
 
@@ -372,6 +373,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 148d93adc84..e6fa845bedc 100644
--- a/src/librustrt/stack.rs
+++ b/src/librustrt/stack.rs
@@ -24,6 +24,28 @@
 //! detection is not guaranteed to continue in the future. Usage of this module
 //! is discouraged unless absolutely necessary.
 
+// iOS related notes
+//
+// It is possible to implement it using idea from
+// http://www.opensource.apple.com/source/Libc/Libc-825.40.1/pthreads/pthread_machdep.h
+//
+// In short: _pthread_{get,set}_specific_direct allows extremely fast
+// access, exactly what is required for segmented stack
+// There is a pool of reserved slots for Apple internal use (0..119)
+// First dynamic allocated pthread key starts with 257 (on iOS7)
+// So using slot 149 should be pretty safe ASSUMING space is reserved
+// for every key < first dynamic key
+//
+// There is also an opportunity to steal keys reserved for Garbage Collection
+// ranges 80..89 and 110..119, especially considering the fact Garbage Collection
+// never supposed to work on iOS. But as everybody knows it - there is a chance
+// that those slots will be re-used, like it happened with key 95 (moved from
+// JavaScriptCore to CoreText)
+//
+// Unfortunately Apple rejected patch to LLVM which generated
+// corresponding prolog, decision was taken to disable segmented
+// stack support on iOS.
+
 pub static RED_ZONE: uint = 20 * 1024;
 
 /// This function is invoked from rust's current __morestack function. Segmented
@@ -151,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")
@@ -173,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")
@@ -193,7 +217,7 @@ pub unsafe fn record_sp_limit(limit: uint) {
     // mips, arm - Some brave soul can port these to inline asm, but it's over
     //             my head personally
     #[cfg(target_arch = "mips")]
-    #[cfg(target_arch = "arm")] #[inline(always)]
+    #[cfg(target_arch = "arm", not(target_os = "ios"))] #[inline(always)]
     unsafe fn target_record_sp_limit(limit: uint) {
         use libc::c_void;
         return record_sp_limit(limit as *c_void);
@@ -201,6 +225,11 @@ pub unsafe fn record_sp_limit(limit: uint) {
             fn record_sp_limit(limit: *c_void);
         }
     }
+
+    // iOS segmented stack is disabled for now, see related notes
+    #[cfg(target_arch = "arm", target_os = "ios")] #[inline(always)]
+    unsafe fn target_record_sp_limit(_: uint) {
+    }
 }
 
 /// The counterpart of the function above, this function will fetch the current
@@ -216,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
@@ -243,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
@@ -267,7 +298,7 @@ pub unsafe fn get_sp_limit() -> uint {
     // mips, arm - Some brave soul can port these to inline asm, but it's over
     //             my head personally
     #[cfg(target_arch = "mips")]
-    #[cfg(target_arch = "arm")] #[inline(always)]
+    #[cfg(target_arch = "arm", not(target_os = "ios"))] #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
         use libc::c_void;
         return get_sp_limit() as uint;
@@ -275,4 +306,12 @@ pub unsafe fn get_sp_limit() -> uint {
             fn get_sp_limit() -> *c_void;
         }
     }
+
+    // iOS doesn't support segmented stacks yet. This function might
+    // be called by runtime though so it is unsafe to mark it as
+    // unreachable, let's return a fixed constant.
+    #[cfg(target_arch = "arm", target_os = "ios")] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        1024
+    }
 }
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 aebed5a8829..80429bb667d 100644
--- a/src/librustrt/unwind.rs
+++ b/src/librustrt/unwind.rs
@@ -283,16 +283,73 @@ 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" {
+        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;
@@ -330,7 +387,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 76dbfa8c29e..79e01c8b966 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::*;
@@ -206,6 +206,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 e2a963c5a87..b98fe8f0aae 100644
--- a/src/libstd/rt/backtrace.rs
+++ b/src/libstd/rt/backtrace.rs
@@ -237,22 +237,63 @@ 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
+    ///
+    /// As mentioned in a huge comment block above, backtrace doesn't
+    /// play well with green threads, so while it is extremely nice
+    /// and simple to use it should be used only on iOS devices as the
+    /// only viable option.
+    #[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 +332,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 +364,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 +389,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 +529,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 +561,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..7ff020d6818 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 {
@@ -159,6 +159,19 @@ impl fmt::Show for Abi {
     }
 }
 
+impl fmt::Show for Os {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            OsLinux => "linux".fmt(f),
+            OsWin32 => "win32".fmt(f),
+            OsMacos => "macos".fmt(f),
+            OsiOS => "ios".fmt(f),
+            OsAndroid => "android".fmt(f),
+            OsFreebsd => "freebsd".fmt(f)
+        }
+    }
+}
+
 #[allow(non_snake_case_functions)]
 #[test]
 fn lookup_Rust() {
diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs
index 4cade394105..79f8cd3379a 100644
--- a/src/libtime/lib.rs
+++ b/src/libtime/lib.rs
@@ -46,7 +46,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};
 
@@ -61,6 +61,7 @@ mod imp {
 
 }
 #[cfg(target_os = "macos")]
+#[cfg(target_os = "ios")]
 mod imp {
     use libc::{timeval, timezone, c_int, mach_timebase_info};
 
@@ -121,6 +122,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 };
@@ -128,7 +130,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);
@@ -160,6 +162,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 };
@@ -173,7 +176,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 {
diff --git a/src/rt/arch/arm/_context.S b/src/rt/arch/arm/_context.S
index fb6db57414a..38fc4827f58 100644
--- a/src/rt/arch/arm/_context.S
+++ b/src/rt/arch/arm/_context.S
@@ -12,8 +12,16 @@
 .align
 #endif
 
-.globl rust_swap_registers
-rust_swap_registers:
+#if defined(__APPLE__)
+  #define SWAP_REGISTERS  _rust_swap_registers
+  #define BOOTSTRAP_TASK  _rust_bootstrap_green_task
+#else
+  #define SWAP_REGISTERS  rust_swap_registers
+  #define BOOTSTRAP_TASK  rust_bootstrap_green_task
+#endif
+        
+.globl SWAP_REGISTERS
+SWAP_REGISTERS:
 	str r0, [r0, #0]
 	str r3, [r0, #12]
 	str r4, [r0, #16]
@@ -53,9 +61,9 @@ rust_swap_registers:
 	mov pc, lr
 
 // For reasons of this existence, see the comments in x86_64/_context.S
-.globl rust_bootstrap_green_task
-rust_bootstrap_green_task:
-        mov r0, r0
-        mov r1, r3
-        mov r2, r4
-        mov pc, r5
+.globl BOOTSTRAP_TASK
+BOOTSTRAP_TASK:
+    mov r0, r0
+    mov r1, r3
+    mov r2, r4
+    mov pc, r5
diff --git a/src/rt/arch/arm/morestack.S b/src/rt/arch/arm/morestack.S
index 219f0962d77..0b9012cc2a8 100644
--- a/src/rt/arch/arm/morestack.S
+++ b/src/rt/arch/arm/morestack.S
@@ -8,33 +8,63 @@
 .text
 .code 32
 .arm
+#if defined(__APPLE__)
+.align 2
+#else
 .align
+#endif
+
+#if defined(__APPLE__)
+#define MORESTACK ___morestack
+#define STACK_EXHAUSTED _rust_stack_exhausted
+#else
+#define MORESTACK __morestack
+#define STACK_EXHAUSTED rust_stack_exhausted
+#endif
+
+.global STACK_EXHAUSTED
+.global MORESTACK
+
+// Unfortunately LLVM yet doesn't support emitting correct debug
+// DWARF information for non-ELF targets so to make it compile
+// on iOS all that directives are simply commented out
+#if defined(__APPLE__)
+#define UNWIND @
+#else
+#define UNWIND
+#endif
 
-.global rust_stack_exhausted
-.global __morestack
-.hidden __morestack
+#if defined(__APPLE__)
+.private_extern MORESTACK
+#else
+.hidden MORESTACK
+#endif
+
+#if !defined(__APPLE__)
+   .type MORESTACK,%function
+#endif
 
 // r4 and r5 are scratch registers for __morestack due to llvm
 // ARMFrameLowering::adjustForSegmentedStacks() implementation.
- .type __morestack,%function
-__morestack:
-	.fnstart
-	// Save frame pointer and return address
-	.save {r4, r5}
-	.save {lr}
-	.save {r6, fp, lr}
+MORESTACK:
+    UNWIND .fnstart
+
+    // Save frame pointer and return address
+    UNWIND .save {r4, r5}
+    UNWIND .save {lr}
+    UNWIND .save {r6, fp, lr}
     push {r6, fp, lr}
 
-	.movsp r6
-	mov r6, sp
-	.setfp fp, sp, #4
-	add fp, sp, #4
+    UNWIND .movsp r6
+    mov r6, sp
+    UNWIND .setfp fp, sp, #4
+    add fp, sp, #4
 
     // Save argument registers of the original function
     push {r0, r1, r2, r3, lr}
 
     // Create new stack
-    bl rust_stack_exhausted@plt
+    bl STACK_EXHAUSTED@plt
 
     // the above function ensures that it never returns
-    .fnend
+    UNWIND  .fnend
diff --git a/src/rt/arch/arm/record_sp.S b/src/rt/arch/arm/record_sp.S
index cce14ed5a3e..d0e9b81b95a 100644
--- a/src/rt/arch/arm/record_sp.S
+++ b/src/rt/arch/arm/record_sp.S
@@ -1,3 +1,9 @@
+// Do not compile anything here for iOS because split stacks
+// are disabled at all and do not need any runtime support.
+//
+// See also comments in librustrt/stack.rs about why it was
+// disabled and how it could be implemented in case of need.
+#if !defined(__APPLE__)
 // Mark stack as non-executable
 #if defined(__linux__) && defined(__ELF__)
 .section	.note.GNU-stack, "", %progbits
@@ -6,16 +12,15 @@
 .text
 .code 32
 .arm
-#if defined(__APPLE__)
-.align 2
-#else
 .align
-#endif
 
-.globl record_sp_limit
-.globl get_sp_limit
+#define RECORD_SP_LIMIT record_sp_limit
+#define GET_SP_LIMIT    get_sp_limit
+
+.globl 	RECORD_SP_LIMIT
+.globl	GET_SP_LIMIT
 
-record_sp_limit:
+RECORD_SP_LIMIT:
 	// First, try to read TLS address from coprocessor
 	mrc p15, #0, r3, c13, c0, #3
 	cmp r3, #0
@@ -27,12 +32,12 @@ record_sp_limit:
 	add r3, r3, #252
 #elif __linux__
 	add r3, r3, #4
-#endif
+#endif // ANDROID
 
 	str r0, [r3]
 	mov pc, lr
 
-get_sp_limit:
+GET_SP_LIMIT:
 	// First, try to read TLS address from coprocessor
 	mrc p15, #0, r3, c13, c0, #3
 	cmp r3, #0
@@ -44,7 +49,8 @@ get_sp_limit:
 	add r3, r3, #252
 #elif __linux__
 	add r3, r3, #4
-#endif
+#endif  // __ANDROID__
 
 	ldr r0, [r3]
 	mov pc, lr
+#endif