diff --git a/mk/platform.mk b/mk/platform.mk index cf6178ec5b043..e789981f49820 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -190,35 +190,72 @@ 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 +## -float-abi=hard -mattr=+vfp3,+v7 -> LLC +## -float-abi=hard -mattr=+vfp3,+v7,+thumb2 -mcpu=cortex-a8 -march=arm -> LLC +## -mcpu=cortex-a8 -mfpu=vfp3 -march=armv7 -> cflags +CFG_SDK_NAME_arm-apple-ios = iphoneos +CFG_SDK_ARCHS_arm-apple-ios = armv7 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_GCCISH_CFLAGS_arm-apple-darwin := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS) -CFG_GCCISH_CXXFLAGS_arm-apple-darwin := -fno-rtti $(CFG_IOS_FLAGS) -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)) -endif +CFG_IOS_FLAGS = -target armv7-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-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) +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_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) +CFG_GCCISH_LINK_FLAGS_arm-apple-ios := -lpthread -L$(CFG_IOS_SDK)/usr/lib -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 +CFG_IOSSIM_SDK = $(shell xcrun --show-sdk-path -sdk iphonesimulator 2>/dev/null) +CFG_IOSSIM_FLAGS = -isysroot $(CFG_IOSSIM_SDK) -I$(CFG_IOSSIM_SDK)/usr/include -I$(CFG_IOSSIM_SDK)/usr/include/c++/4.2.1 +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) +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_GCCISH_CFLAGS_i386-apple-ios := -Wall -Werror -g -fPIC -m32 $(CFG_IOSSIM_FLAGS) -arch i386 +CFG_GCCISH_CXXFLAGS_i386-apple-ios := -fno-rtti $(CFG_IOSSIM_FLAGS) +CFG_GCCISH_LINK_FLAGS_i386-apple-ios := -lpthread -Wl,-no_compact_unwind -m32 +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)) # x86_64-apple-darwin configuration CC_x86_64-apple-darwin=$(CC) diff --git a/mk/rt.mk b/mk/rt.mk index 77bb22b7bfc69..2aaff37bfa4fa 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -169,6 +169,7 @@ 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_XCODEPROJ_$(1) := $$(S)src/libuv/uv-$(1).xcodeproj LIBUV_STAMP_$(1) = $$(LIBUV_DIR_$(1))/libuv-auto-clean-stamp @@ -200,6 +201,30 @@ $$(LIBUV_LIB_$(1)): $$(LIBUV_DEPS) $$(MKFILE_DEPS) AR="$$(AR_$(1))" \ V=$$(VERBOSE) $$(Q)cp $$(S)src/libuv/libuv.a $$@ +else ifeq ($(OSTYPE_$(1)), apple-ios) # iOS + +$$(LIBUV_XCODEPROJ_$(1)): $$(LIBUV_DEPS) $$(MKFILE_DEPS) $$(LIBUV_STAMP_$(1)) + (cd $(S)src/libuv/ && \ + $$(CFG_PYTHON) ./gyp_uv.py -f xcode \ + -D ninja \ + -R libuv) + touch $$@ + +LIBUV_XCODE_OUT_LIB_$(1) := $$(S)src/libuv/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 $$(S)src/libuv/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_LIB_$(1)): $$(LIBUV_DIR_$(1))/Release/libuv.a $$(MKFILE_DEPS) $$(Q)cp $$< $$@ @@ -216,7 +241,6 @@ $$(LIBUV_DIR_$(1))/Release/libuv.a: $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)) \ NO_LOAD="$$(LIBUV_NO_LOAD)" \ V=$$(VERBOSE) $$(Q)touch $$@ - endif ################################################################################ @@ -270,6 +294,11 @@ $$(BACKTRACE_LIB_$(1)): touch $$@ else +ifeq ($$(findstring ios,$$(OSTYPE_$(1))),ios) +$$(BACKTRACE_LIB_$(1)): + touch $$@ +else + ifeq ($$(CFG_WINDOWSY_$(1)),1) $$(BACKTRACE_LIB_$(1)): touch $$@ @@ -315,6 +344,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/liblibc/lib.rs b/src/liblibc/lib.rs index f25734e1e2169..bc29e728f65dc 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -271,10 +271,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}; @@ -1264,6 +1267,7 @@ pub mod types { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] pub mod os { pub mod common { pub mod posix01 { @@ -3034,6 +3038,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}; @@ -3698,6 +3703,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_ { @@ -3712,6 +3718,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")] @@ -3724,6 +3731,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")] @@ -3896,6 +3904,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_ { @@ -3906,6 +3915,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")] @@ -4015,6 +4025,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 { @@ -4095,6 +4106,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}; @@ -4157,6 +4169,10 @@ pub mod funcs { } } + #[cfg(target_os = "ios")] + pub mod extra { + } + #[cfg(target_os = "freebsd")] pub mod extra { } diff --git a/src/libnative/io/file_unix.rs b/src/libnative/io/file_unix.rs index 5446ab2950e44..c20b0f6d9591b 100644 --- a/src/libnative/io/file_unix.rs +++ b/src/libnative/io/file_unix.rs @@ -150,6 +150,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) } } @@ -157,7 +158,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 78d17bc8d747f..70dda133e66d8 100644 --- a/src/libnative/io/mod.rs +++ b/src/libnative/io/mod.rs @@ -53,6 +53,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 2e64b82a84a31..b9946f69e0482 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -283,6 +283,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) @@ -292,7 +293,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 e3bb938995bf3..ae6599d6dbc58 100644 --- a/src/libnative/io/process.rs +++ b/src/libnative/io/process.rs @@ -478,6 +478,7 @@ fn spawn_process_os(config: p::ProcessConfig, extern { fn ioctl(fd: c_int, req: c_ulong) -> c_int; } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] static FIOCLEX: c_ulong = 0x20006601; #[cfg(target_os = "linux")] @@ -747,6 +748,7 @@ fn translate_status(status: c_int) -> p::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 0a38a6ff0be35..2723a5b546cdc 100644 --- a/src/libnative/io/timer_unix.rs +++ b/src/libnative/io/timer_unix.rs @@ -285,6 +285,7 @@ impl Drop for Timer { } #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] mod imp { use libc; diff --git a/src/librand/os.rs b/src/librand/os.rs index ed4c7299dffb8..21190cec48f71 100644 --- a/src/librand/os.rs +++ b/src/librand/os.rs @@ -13,7 +13,7 @@ pub use self::imp::OSRng; -#[cfg(unix)] +#[cfg(unix, not(target_os = "ios"))] mod imp { use Rng; use reader::ReaderRng; @@ -26,7 +26,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 { @@ -56,6 +56,59 @@ mod imp { } } +#[cfg(target_os = "ios")] +#[link(name = "Security", kind = "framework")] +mod imp { + extern crate libc; + + use Rng; + use std::cast; + use std::io::{IoResult}; + use std::os; + use self::libc::{c_int, size_t, c_uint}; + + pub struct OSRng; + + static kSecRandomDefault: c_uint = 0; + + extern "C" { + fn SecRandomCopyBytes(rnd: c_uint, count: size_t, bytes: *mut u8) -> c_int; + } + + impl OSRng { + /// Create a new `OSRng`. + pub fn new() -> IoResult { + Ok(OSRng) + } + } + + impl Rng for OSRng { + fn next_u32(&mut self) -> u32 { + let mut v = [0u8, .. 4]; + self.fill_bytes(v); + unsafe { cast::transmute(v) } + } + fn next_u64(&mut self) -> u64 { + let mut v = [0u8, .. 8]; + self.fill_bytes(v); + unsafe { cast::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()); + } + } + } + + impl Drop for OSRng { + fn drop(&mut self) { + } + } +} + #[cfg(windows)] mod imp { extern crate libc; diff --git a/src/librustc/back/arm.rs b/src/librustc/back/arm.rs index f86c87af72674..041958d1653b4 100644 --- a/src/librustc/back/arm.rs +++ b/src/librustc/back/arm.rs @@ -33,6 +33,14 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs:: "-a0:0:64-n32" } + 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" + } + 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 9ac99b267169e..16aafb10deb7f 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -111,6 +111,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 => { @@ -119,7 +126,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() } } @@ -167,6 +177,9 @@ pub mod write { }; let tm = sess.targ_cfg.target_strs.target_triple.with_c_str(|t| { + // No segmented stack support on iOS yet + let supports_segmented_stack = !(sess.targ_cfg.os == abi::OsiOS && + sess.targ_cfg.arch == abi::Arm); sess.opts.cg.target_cpu.with_c_str(|cpu| { target_feature(sess).with_c_str(|features| { llvm::LLVMRustCreateTargetMachine( @@ -174,7 +187,7 @@ pub mod write { lib::llvm::CodeModelDefault, reloc_model, opt_level, - true, + supports_segmented_stack, use_softfp, no_fp_elim ) @@ -821,14 +834,20 @@ pub fn filename_for_input(sess: &Session, crate_type: session::CrateType, out_filename.with_filename(format!("lib{}.rlib", libname)) } session::CrateTypeDylib => { - let (prefix, suffix) = match sess.targ_cfg.os { - abi::OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX), - abi::OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX), - abi::OsLinux => (linux::DLL_PREFIX, linux::DLL_SUFFIX), - abi::OsAndroid => (android::DLL_PREFIX, android::DLL_SUFFIX), - abi::OsFreebsd => (freebsd::DLL_PREFIX, 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 => (win32::DLL_PREFIX, win32::DLL_SUFFIX), + abi::OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX), + abi::OsLinux => (linux::DLL_PREFIX, linux::DLL_SUFFIX), + abi::OsAndroid => (android::DLL_PREFIX, android::DLL_SUFFIX), + abi::OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX), + abi::OsiOS => unreachable!(), + }; + out_filename.with_filename(format!("{}{}{}", prefix, libname, suffix)) + } } session::CrateTypeStaticlib => { out_filename.with_filename(format!("lib{}.a", libname)) @@ -877,7 +896,14 @@ fn link_binary_output(sess: &Session, link_natively(sess, false, &obj_filename, &out_filename); } session::CrateTypeDylib => { - link_natively(sess, true, &obj_filename, &out_filename); + if sess.targ_cfg.os == abi::OsiOS { + sess.note(format!("No dylib for iOS -> saving static library {} to {}", + obj_filename.display(), out_filename.display())); + link_staticlib(sess, &obj_filename, &out_filename); + } + else { + link_natively(sess, true, &obj_filename, &out_filename); + } } } @@ -974,7 +1000,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(); } } } @@ -1066,7 +1092,8 @@ fn link_natively(sess: &Session, dylib: bool, obj_filename: &Path, // 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) { + if (sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS) + && (sess.opts.debuginfo != NoDebugInfo) { // FIXME (#9639): This needs to handle non-utf8 paths match Process::status("dsymutil", [out_filename.as_str().unwrap().to_owned()]) { diff --git a/src/librustc/back/mips.rs b/src/librustc/back/mips.rs index 9667d7b84e9c0..0a9b392424c68 100644 --- a/src/librustc/back/mips.rs +++ b/src/librustc/back/mips.rs @@ -20,7 +20,7 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs:: meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(), data_layout: match target_os { - abi::OsMacos => { + abi::OsMacos | 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" + diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index e455c4ad23ce0..c0c5130615b19 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -119,7 +119,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 9b22c82e91776..67fa24409f5d6 100644 --- a/src/librustc/back/x86.rs +++ b/src/librustc/back/x86.rs @@ -21,7 +21,7 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs:: meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(), data_layout: match target_os { - abi::OsMacos => { + abi::OsMacos | 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" + diff --git a/src/librustc/back/x86_64.rs b/src/librustc/back/x86_64.rs index 524ae5e552484..5e5bf6dfe9f0d 100644 --- a/src/librustc/back/x86_64.rs +++ b/src/librustc/back/x86_64.rs @@ -21,7 +21,7 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs:: meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(), data_layout: match target_os { - abi::OsMacos => { + abi::OsMacos | 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" diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 4fc7239e63b18..da955bf899dd2 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -86,6 +86,7 @@ pub fn default_configuration(sess: &Session) -> 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 @@ -744,6 +745,7 @@ static os_names : &'static [(&'static str, abi::Os)] = &'static [ ("mingw32", abi::OsWin32), ("win32", abi::OsWin32), ("darwin", abi::OsMacos), + ("ios", abi::OsiOS), ("android", abi::OsAndroid), ("linux", abi::OsLinux), ("freebsd", abi::OsFreebsd)]; diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 0cd0ac557787d..8e99372bda63f 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -553,6 +553,7 @@ pub fn sess_os_to_meta_os(os: abi::Os) -> metadata::loader::Os { abi::OsLinux => loader::OsLinux, abi::OsAndroid => loader::OsAndroid, abi::OsMacos => loader::OsMacos, + abi::OsiOS => loader::OsiOS, abi::OsFreebsd => loader::OsFreebsd } } diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index e6b7049f4f8fa..a63cafc59534b 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 5a342e39d701a..d02edf892fcfb 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -43,7 +43,8 @@ pub enum Os { OsWin32, OsLinux, OsAndroid, - OsFreebsd + OsFreebsd, + OsiOS } pub struct HashMismatch { @@ -403,6 +404,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 => (macos::DLL_PREFIX, macos::DLL_SUFFIX), } } } @@ -527,6 +529,7 @@ fn get_metadata_section_imp(os: Os, filename: &Path) -> Result &'static str { match os { OsMacos => "__DATA,__note.rustc", + OsiOS => "__DATA,__note.rustc", OsWin32 => ".note.rustc", OsLinux => ".note.rustc", OsAndroid => ".note.rustc", @@ -537,6 +540,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 93b6fdd8988c5..d10f6b72820d2 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/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 0514642c58390..c7c0a7149403a 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -276,7 +276,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)); } diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index 76341d21e9ac6..592a530cb54b4 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/libstd/comm/mod.rs b/src/libstd/comm/mod.rs index 7700000b8693c..70bcc153d8c1e 100644 --- a/src/libstd/comm/mod.rs +++ b/src/libstd/comm/mod.rs @@ -576,16 +576,24 @@ impl Clone for Sender { let (packet, sleeper) = match self.inner { Oneshot(ref p) => { let (a, b) = UnsafeArc::new2(shared::Packet::new()); - match unsafe { (*p.get()).upgrade(Receiver::new(Shared(a))) } { - oneshot::UpSuccess | oneshot::UpDisconnected => (b, None), - oneshot::UpWoke(task) => (b, Some(task)) + unsafe { + (*b.get()).postinit_lock(); + + match (*p.get()).upgrade(Receiver::new(Shared(a))) { + oneshot::UpSuccess | oneshot::UpDisconnected => (b, None), + oneshot::UpWoke(task) => (b, Some(task)) + } } } Stream(ref p) => { let (a, b) = UnsafeArc::new2(shared::Packet::new()); - match unsafe { (*p.get()).upgrade(Receiver::new(Shared(a))) } { - stream::UpSuccess | stream::UpDisconnected => (b, None), - stream::UpWoke(task) => (b, Some(task)), + unsafe { + (*b.get()).postinit_lock(); + + match (*p.get()).upgrade(Receiver::new(Shared(a))) { + stream::UpSuccess | stream::UpDisconnected => (b, None), + stream::UpWoke(task) => (b, Some(task)), + } } } Shared(ref p) => { diff --git a/src/libstd/comm/shared.rs b/src/libstd/comm/shared.rs index 525786f5d1e76..71b18e75acbe2 100644 --- a/src/libstd/comm/shared.rs +++ b/src/libstd/comm/shared.rs @@ -66,7 +66,8 @@ pub enum Failure { } impl Packet { - // Creation of a packet *must* be followed by a call to inherit_blocker + // Creation of a packet *must* be followed by a call to postinit_lock + // and later by inherit_blocker pub fn new() -> Packet { let p = Packet { queue: mpsc::Queue::new(), @@ -78,11 +79,18 @@ impl Packet { sender_drain: atomics::AtomicInt::new(0), select_lock: unsafe { NativeMutex::new() }, }; - // see comments in inherit_blocker about why we grab this lock - unsafe { p.select_lock.lock_noguard() } return p; } + // This function should be used after newly created Packet + // was wrapped with an Arc + // In other case mutex data will be duplicated while clonning + // and that could cause problems on platforms where it is + // represented by opaque data structure + pub fn postinit_lock(&mut self) { + unsafe { self.select_lock.lock_noguard() } + } + // This function is used at the creation of a shared packet to inherit a // previously blocked task. This is done to prevent spurious wakeups of // tasks in select(). diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 25f503174bc98..cfdfba35dc6f3 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -469,6 +469,12 @@ pub fn self_exe_name() -> Option { } } + #[cfg(target_os = "ios")] + fn load_self() -> Option<~[u8]> { + // FIXME: [iOS] recheck + None + } + #[cfg(windows)] fn load_self() -> Option<~[u8]> { use str::OwnedStr; @@ -622,6 +628,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 { @@ -670,6 +677,7 @@ pub fn error_string(errnum: uint) -> ~str { #[cfg(unix)] fn strerror(errnum: uint) -> ~str { #[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) @@ -828,7 +836,12 @@ fn real_args_as_bytes() -> ~[~[u8]] { } } -#[cfg(not(windows))] +#[cfg(target_os = "ios")] +fn real_args() -> ~[~str] { + ~[] // There are no command line arguments on iOS :( +} + +#[cfg(not(windows), not(target_os = "ios"))] fn real_args() -> ~[~str] { real_args_as_bytes().move_iter().map(|v| str::from_utf8_lossy(v).into_owned()).collect() } @@ -896,10 +909,16 @@ pub fn args() -> ~[~str] { /// Returns the arguments which this program was started with (normally passed /// via the command line) as byte vectors. +#[cfg(not(target_os = "ios"))] pub fn args_as_bytes() -> ~[~[u8]] { real_args_as_bytes() } +#[cfg(target_os = "ios")] +pub fn args_as_bytes() -> ~[~[u8]] { + ~[] +} + #[cfg(target_os = "macos")] extern { // These functions are in crt_externs.h. @@ -1304,6 +1323,9 @@ pub mod consts { #[cfg(target_os = "macos")] pub use os::consts::macos::{EXE_SUFFIX, EXE_EXTENSION}; + #[cfg(target_os = "ios")] + pub use os::consts::ios::*; + #[cfg(target_os = "freebsd")] pub use os::consts::freebsd::{SYSNAME, DLL_PREFIX, DLL_SUFFIX, DLL_EXTENSION}; #[cfg(target_os = "freebsd")] @@ -1377,6 +1399,33 @@ pub mod consts { pub static EXE_EXTENSION: &'static str = ""; } + /// Constants for iOS systems. Most of them are useless + pub mod ios { + /// A string describing the specific operating system in use: in this + /// case, `macos`. + pub static SYSNAME: &'static str = "ios"; + + /// Specifies the filename prefix used for shared libraries on this + /// platform: in this case, `lib`. + pub static DLL_PREFIX: &'static str = "lib"; + + /// Specifies the filename suffix used for shared libraries on this + /// platform: in this case, `.dylib`. + pub static DLL_SUFFIX: &'static str = ".dylib"; + + /// Specifies the file extension used for shared libraries on this + /// platform that goes after the dot: in this case, `dylib`. + pub static DLL_EXTENSION: &'static str = "dylib"; + + /// 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 = ""; + } + /// Constants for FreeBSD systems. pub mod freebsd { /// A string describing the specific operating system in use: in this diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index 328de69691436..9e508378539c1 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -165,6 +165,7 @@ mod imp { } #[cfg(target_os = "macos", not(test))] +#[cfg(target_os = "ios", not(test))] #[cfg(target_os = "win32", not(test))] mod imp { use option::Option; diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index bf8c15c20abbd..c8739c3f068fb 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -318,6 +318,7 @@ mod imp { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] // FIXME: [iOS] check if it ever will work fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> { use intrinsics; struct Dl_info { @@ -341,7 +342,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 container::Container; use iter::Iterator; diff --git a/src/libstd/rt/libunwind.rs b/src/libstd/rt/libunwind.rs index 4fd610d742360..6651bb97f5dcb 100644 --- a/src/libstd/rt/libunwind.rs +++ b/src/libstd/rt/libunwind.rs @@ -16,6 +16,7 @@ use libc; #[cfg(not(target_arch = "arm"))] +#[cfg(target_os = "ios")] #[repr(C)] pub enum _Unwind_Action { _UA_SEARCH_PHASE = 1, @@ -93,9 +94,12 @@ extern {} extern {} extern "C" { + #[cfg(not(target_os = "ios"))] pub fn _Unwind_RaiseException(exception: *_Unwind_Exception) -> _Unwind_Reason_Code; pub fn _Unwind_DeleteException(exception: *_Unwind_Exception); + + #[cfg(not(target_os = "ios"))] pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn, trace_argument: *libc::c_void) -> _Unwind_Reason_Code; @@ -108,6 +112,26 @@ extern "C" { pub fn _Unwind_FindEnclosingFunction(pc: *libc::c_void) -> *libc::c_void; } +#[cfg(target_os = "ios")] +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) +} + +// On iOS there is no any backtrace function available in +// native libunwind, perhaps it should be emulated manually +#[cfg(target_os = "ios")] +pub unsafe fn _Unwind_Backtrace(_: _Unwind_Trace_Fn, + _: *libc::c_void) + -> _Unwind_Reason_Code +{ + _URC_FAILURE +} + // On android, the function _Unwind_GetIP is a macro, and this is the expansion // of the macro. This is all copy/pasted directly from the header file with the // definition of _Unwind_GetIP. diff --git a/src/libstd/rt/local_ptr.rs b/src/libstd/rt/local_ptr.rs index ff82be97489b5..ae54de2b2ab35 100644 --- a/src/libstd/rt/local_ptr.rs +++ b/src/libstd/rt/local_ptr.rs @@ -23,10 +23,11 @@ use ptr::RawPtr; #[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}; @@ -80,7 +81,7 @@ pub unsafe fn borrow() -> Borrowed { /// 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 cast; use option::{Option, Some, None}; diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index f4a4fd9ab2e9b..ab5a5a562cdab 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -76,7 +76,7 @@ pub use self::unwind::{begin_unwind, begin_unwind_raw, begin_unwind_fmt}; 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/libstd/rt/thread.rs b/src/libstd/rt/thread.rs index 4aa85bc4c72a6..f2e2e6d08638c 100644 --- a/src/libstd/rt/thread.rs +++ b/src/libstd/rt/thread.rs @@ -258,10 +258,11 @@ mod imp { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] #[cfg(target_os = "android")] pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); } - #[cfg(not(target_os = "macos"), not(target_os = "android"))] + #[cfg(not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android"))] pub unsafe fn yield_now() { assert_eq!(pthread_yield(), 0); } // glibc >= 2.15 has a __pthread_get_minstack() function that returns @@ -312,9 +313,10 @@ mod imp { fn pthread_detach(thread: libc::pthread_t) -> libc::c_int; #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] #[cfg(target_os = "android")] fn sched_yield() -> libc::c_int; - #[cfg(not(target_os = "macos"), not(target_os = "android"))] + #[cfg(not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android"))] fn pthread_yield() -> libc::c_int; } } @@ -338,4 +340,3 @@ mod tests { assert_eq!(42, Thread::start_stack(1, proc () 42).join()); } } - diff --git a/src/libstd/rt/thread_local_storage.rs b/src/libstd/rt/thread_local_storage.rs index 2f567e91b4cdb..da1eced2b2db9 100644 --- a/src/libstd/rt/thread_local_storage.rs +++ b/src/libstd/rt/thread_local_storage.rs @@ -40,13 +40,14 @@ pub unsafe fn destroy(key: Key) { assert_eq!(0, pthread_key_delete(key)); } -#[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/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index 68d63949ae601..533c413b94f14 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -239,16 +239,71 @@ 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) + } + } + } +} + +#[cfg(target_os = "ios", target_arch = "arm", not(test))] +#[doc(hidden)] +#[allow(visible_private_types)] +pub mod eabi { + use uw = rt::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 = rt::libunwind; diff --git a/src/libstd/rtdeps.rs b/src/libstd/rtdeps.rs index f954bcabe5aa9..8ca89aa2304c6 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/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs index 441a60a518626..d3669f6009a80 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/unstable/dynamic_lib.rs @@ -14,7 +14,8 @@ Dynamic library facilities. A simple wrapper over the platform's dynamic library facilities -*/ + */ + use c_str::ToCStr; use cast; use path; @@ -79,7 +80,7 @@ impl DynamicLibrary { } } -#[cfg(test)] +#[cfg(test, not(target_os = "ios"))] mod test { use super::*; use prelude::*; @@ -130,6 +131,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 c_str::ToCStr; diff --git a/src/libstd/unstable/mutex.rs b/src/libstd/unstable/mutex.rs index c2db8ad9586ee..8c8dcd960b916 100644 --- a/src/libstd/unstable/mutex.rs +++ b/src/libstd/unstable/mutex.rs @@ -98,6 +98,7 @@ impl StaticNativeMutex { /// /// Note that a mutex created in this way needs to be explicit /// freed with a call to `destroy` or it will leak. + /// Also it is important to avoid locking until mutex has stopped moving pub unsafe fn new() -> StaticNativeMutex { StaticNativeMutex { inner: imp::Mutex::new() } } @@ -172,6 +173,7 @@ impl NativeMutex { /// /// The user must be careful to ensure the mutex is not locked when its is /// being destroyed. + /// Also it is important to avoid locking until mutex has stopped moving pub unsafe fn new() -> NativeMutex { NativeMutex { inner: StaticNativeMutex::new() } } @@ -262,7 +264,6 @@ mod imp { use libc; use self::os::{PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, pthread_mutex_t, pthread_cond_t}; - use mem; use ty::Unsafe; use kinds::marker; @@ -283,6 +284,7 @@ mod imp { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] mod os { use libc; @@ -294,6 +296,11 @@ 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; @@ -389,14 +396,14 @@ mod imp { impl Mutex { pub unsafe fn new() -> Mutex { + // As mutex might be moved and address is changing it + // is better to avoid initialization of potentially + // opaque OS data before it landed let m = Mutex { - lock: Unsafe::new(mem::init()), - cond: Unsafe::new(mem::init()), + lock: Unsafe::new(PTHREAD_MUTEX_INITIALIZER), + cond: Unsafe::new(PTHREAD_COND_INITIALIZER), }; - pthread_mutex_init(m.lock.get(), 0 as *libc::c_void); - pthread_cond_init(m.cond.get(), 0 as *libc::c_void); - return m; } @@ -416,11 +423,7 @@ mod imp { } extern { - fn pthread_mutex_init(lock: *mut pthread_mutex_t, - attr: *pthread_mutexattr_t) -> libc::c_int; fn pthread_mutex_destroy(lock: *mut pthread_mutex_t) -> libc::c_int; - fn pthread_cond_init(cond: *mut pthread_cond_t, - attr: *pthread_condattr_t) -> libc::c_int; fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> libc::c_int; fn pthread_mutex_lock(lock: *mut pthread_mutex_t) -> libc::c_int; fn pthread_mutex_trylock(lock: *mut pthread_mutex_t) -> libc::c_int; diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index 17251d31351ab..0f8d977d5031a 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -11,7 +11,7 @@ use std::fmt; #[deriving(Eq)] -pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, } +pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, OsiOS, } #[deriving(Eq, TotalEq, Hash, Encodable, Decodable, Clone)] pub enum Abi { diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index d50ecc2a2abf8..f938d84049e89 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -41,7 +41,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}; @@ -56,6 +56,7 @@ mod imp { } #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] mod imp { use libc::{timeval, timezone, c_int, mach_timebase_info}; @@ -116,6 +117,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 }; @@ -123,7 +125,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); @@ -155,6 +157,7 @@ pub fn precise_time_ns() -> u64 { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] fn os_precise_time_ns() -> u64 { let time = unsafe { imp::mach_absolute_time() }; let mut info = libc::mach_timebase_info { numer: 0, denom: 0 }; @@ -162,7 +165,7 @@ pub fn precise_time_ns() -> u64 { return time * ((info.numer / info.denom) as 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 fb6db57414a56..77301f07662cb 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,8 +61,8 @@ 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: +.globl BOOTSTRAP_TASK +BOOTSTRAP_TASK: mov r0, r0 mov r1, r3 mov r2, r4 diff --git a/src/rt/arch/arm/morestack.S b/src/rt/arch/arm/morestack.S index 219f0962d771c..466ac76d5be23 100644 --- a/src/rt/arch/arm/morestack.S +++ b/src/rt/arch/arm/morestack.S @@ -8,27 +8,46 @@ .text .code 32 .arm +#if defined(__APPLE__) +.align 2 +#else .align +#endif .global rust_stack_exhausted .global __morestack + +#if defined(__APPLE__) +.private_extern __morestack +#else .hidden __morestack +#endif // r4 and r5 are scratch registers for __morestack due to llvm // ARMFrameLowering::adjustForSegmentedStacks() implementation. - .type __morestack,%function +#if !defined(__APPLE__) + .type __morestack,%function +#endif + +#if defined(__APPLE__) +#define UNWIND @ +#else +#define UNWIND +#endif + __morestack: - .fnstart - // Save frame pointer and return address - .save {r4, r5} - .save {lr} - .save {r6, fp, lr} + 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} @@ -37,4 +56,4 @@ __morestack: bl rust_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 cce14ed5a3ecf..73095c0c660af 100644 --- a/src/rt/arch/arm/record_sp.S +++ b/src/rt/arch/arm/record_sp.S @@ -12,10 +12,28 @@ .align #endif -.globl record_sp_limit -.globl get_sp_limit +#if defined(__APPLE__) + #define RECORD_SP_LIMIT _record_sp_limit + #define GET_SP_LIMIT _get_sp_limit +#else + #define RECORD_SP_LIMIT record_sp_limit + #define GET_SP_LIMIT get_sp_limit +#endif + +.globl RECORD_SP_LIMIT +.globl GET_SP_LIMIT + + // Apple implementation for now is absolutely empty + // as there is no hardware TLS and emulating + // it is too expensive for every function call + + // NOTE: although there is Android and Linux + // implementations, they are actually for kernel mode + // only, i.e. if you plan to use rust in user space + // you'll need probably disable them -record_sp_limit: +RECORD_SP_LIMIT: +#if !defined(__APPLE__) // First, try to read TLS address from coprocessor mrc p15, #0, r3, c13, c0, #3 cmp r3, #0 @@ -27,12 +45,19 @@ record_sp_limit: add r3, r3, #252 #elif __linux__ add r3, r3, #4 -#endif +#endif // ANDROID str r0, [r3] +#endif // __APPLE__ mov pc, lr -get_sp_limit: +GET_SP_LIMIT: +#if defined(__APPLE__) + // just an placeholder, considering 512Kb limit for stack on secondary thread + // anyway, stacked segments are disabled for iOS so this function + // shouldn't be called at all + mov r0, 65536 +#else // First, try to read TLS address from coprocessor mrc p15, #0, r3, c13, c0, #3 cmp r3, #0 @@ -44,7 +69,8 @@ get_sp_limit: add r3, r3, #252 #elif __linux__ add r3, r3, #4 -#endif +#endif // __ANDROID__ ldr r0, [r3] +#endif // __APPLE__ mov pc, lr