diff --git a/mk/platform.mk b/mk/platform.mk index 3ab55ce4b7b1b..1efa1cc5b6d85 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 1c4efd641f063..7fc82ef6269d8 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 index ed112ca1e4275..7b97b8468f061 160000 --- a/src/compiler-rt +++ b/src/compiler-rt @@ -1 +1 @@ -Subproject commit ed112ca1e4275e1c5707a898f2bf6164707ba378 +Subproject commit 7b97b8468f0614072cf3299fa8c51e85f609316f diff --git a/src/jemalloc b/src/jemalloc index 6a96910f2eaea..024c67ad651e1 160000 --- a/src/jemalloc +++ b/src/jemalloc @@ -1 +1 @@ -Subproject commit 6a96910f2eaea6d2c705bb12379b23576b30d7d5 +Subproject commit 024c67ad651e1a3ca228936c4cfb13a37329baf2 diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index ff87b7fb0074b..9ed0d50a03e8a 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 e6cb5cb76f11e..70fd6310070da 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 fda9b7b1932b0..f521934c0f965 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 4158db7bb8ea1..6dc2482ab0c7d 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 e7effbd6bdbfb..30ea80a1296c7 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 d8486cb9f0942..f26d87ba1b52f 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 11f9c4b3d8cb8..ca0a810890c27 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, _: ()) { + +// 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, _: 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, _: ()) { impl Timer { pub fn new() -> IoResult { - 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 e5e8126ace184..7a7d248a4cbf5 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 55998f254ed4a..d644a0cc35330 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 { 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 9f640a2c9cbe0..8f3da03e825ea 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 cdf49304f9a75..a458cf22a5bdc 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 ed5976ad508ba..7928f3d8db098 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 , diff --git a/src/librustc/back/x86.rs b/src/librustc/back/x86.rs index 3ef013d47c91d..d2dac03267d5f 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 80dd2b2c51629..c2eae18737bfa 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 186db839e33d8..fd21951f2875a 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 { @@ -354,18 +354,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"), @@ -373,6 +361,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { abi::OsLinux => InternedString::new("linux"), abi::OsAndroid => InternedString::new("android"), abi::OsFreebsd => InternedString::new("freebsd"), + abi::OsiOS => InternedString::new("ios"), }; // ARM is bi-endian, however using NDK seems to default @@ -438,7 +427,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 { for &(arch, abi) in architecture_abis.iter() { @@ -772,6 +762,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 d703ece307ffb..7bc698bfbd342 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -779,17 +779,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 b6205d8d54e67..952e8afcbecec 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 773b9e6e0aac4..bc22b3ca7e242 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -249,4 +249,3 @@ pub fn expect(sess: &Session, opt: Option, msg: || -> String) -> T { diagnostic::expect(sess.diagnostic(), opt, msg) } - diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 4df21fbc974be..efe28614b8f4d 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 cfda97ad26fd7..978246b2436e8 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, pub rejected_via_hash: Vec, @@ -174,10 +167,12 @@ impl<'a> Context<'a> { } fn find_library_crate(&mut self) -> Option { - 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(); @@ -218,12 +213,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, |_| { @@ -448,13 +445,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, } } @@ -496,7 +494,7 @@ impl ArchiveMetadata { } // Just a small wrapper to time how long reading metadata takes. -fn get_metadata_section(os: Os, filename: &Path) -> Result { +fn get_metadata_section(os: abi::Os, filename: &Path) -> Result { let start = time::precise_time_ns(); let ret = get_metadata_section_imp(os, filename); info!("reading {} => {}ms", filename.filename_display(), @@ -504,7 +502,7 @@ fn get_metadata_section(os: Os, filename: &Path) -> Result return ret; } -fn get_metadata_section_imp(os: Os, filename: &Path) -> Result { +fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result { if !filename.exists() { return Err(format!("no such file: '{}'", filename.display())); } @@ -590,28 +588,30 @@ fn get_metadata_section_imp(os: Os, filename: &Path) -> Result &'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 9cebc79171f5f..3fec3cbd1bbc2 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}; @@ -172,12 +172,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()) } }); @@ -196,17 +196,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 @@ -221,7 +224,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 } @@ -250,7 +253,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 { @@ -1877,7 +1880,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 } @@ -1909,7 +1912,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) @@ -2278,12 +2281,8 @@ pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec { }); 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 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/cleanup.rs b/src/librustc/middle/trans/cleanup.rs index b28db3d378be7..24f30bae75a91 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 a80ae9e2596da..68c6f1752bdfe 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 { 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 $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 db17000abb32b..c50badac531a9 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -277,7 +277,8 @@ pub fn finalize(cx: &CrateContext) { // instruct LLVM to emit an older version of dwarf, however, // for OS X to understand. For more info see #11352 // This can be overridden using --llvm-opts -dwarf-version,N. - if cx.sess().targ_cfg.os == abi::OsMacos { + if cx.sess().targ_cfg.os == abi::OsMacos || + cx.sess().targ_cfg.os == abi::OsiOS { "Dwarf Version".with_c_str( |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2)); } else { diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 96aa7267d231a..ef9bf4eebe24b 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 8ad10a686e677..800e7f065f1e6 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 0789bf7f906f6..d6d4b18051bf3 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 76cbeef443eae..e17a43322ba37 100644 --- a/src/librustrt/lib.rs +++ b/src/librustrt/lib.rs @@ -164,7 +164,7 @@ pub unsafe fn cleanup() { pub mod shouldnt_be_public { #[cfg(not(test))] pub use super::local_ptr::native::maybe_tls_key; - #[cfg(not(windows), not(target_os = "android"))] + #[cfg(not(windows), not(target_os = "android"), not(target_os = "ios"))] pub use super::local_ptr::compiled::RT_TLS_PTR; } diff --git a/src/librustrt/libunwind.rs b/src/librustrt/libunwind.rs index 846ec248805e9..2d58c1bee15bd 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 91e3409892ea5..b6858be32b7ce 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() -> 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 core::prelude::*; diff --git a/src/librustrt/mutex.rs b/src/librustrt/mutex.rs index eec19e9d5db86..26359ff7f6e9a 100644 --- a/src/librustrt/mutex.rs +++ b/src/librustrt/mutex.rs @@ -283,6 +283,7 @@ mod imp { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] mod os { use libc; @@ -294,6 +295,10 @@ mod imp { static __PTHREAD_MUTEX_SIZE__: uint = 40; #[cfg(target_arch = "x86")] static __PTHREAD_COND_SIZE__: uint = 24; + #[cfg(target_arch = "arm")] + static __PTHREAD_MUTEX_SIZE__: uint = 40; + #[cfg(target_arch = "arm")] + static __PTHREAD_COND_SIZE__: uint = 24; static _PTHREAD_MUTEX_SIG_init: libc::c_long = 0x32AAABA7; static _PTHREAD_COND_SIG_init: libc::c_long = 0x3CB0B1BB; diff --git a/src/librustrt/stack.rs b/src/librustrt/stack.rs index 148d93adc8485..e6fa845bedc89 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 4ef2cec19db9b..3dcd1c4a6f0d3 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 2cdeb21fb83dd..4a7be39e6b87a 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 f7475db1552f7..5b941c9d5aa39 100644 --- a/src/librustrt/unwind.rs +++ b/src/librustrt/unwind.rs @@ -285,16 +285,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; @@ -332,7 +389,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 fa6efc8a4b18a..5dbed6844c35f 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -153,7 +153,7 @@ impl DynamicLibrary { } } -#[cfg(test)] +#[cfg(test, not(target_os = "ios"))] mod test { use super::*; use prelude::*; @@ -205,6 +205,7 @@ mod test { #[cfg(target_os = "linux")] #[cfg(target_os = "android")] #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] pub mod dl { use prelude::*; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index cc76cde7baffc..f6b1c04dd34c6 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 { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] fn load_self() -> Option> { 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> { } } +// 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> { + 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 2654b7a1acc6a..f507011c2b955 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 { + 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 a1372b51d472a..0e3e7cc796a3d 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, + /// 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, + } + // 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 c804918ae4b41..f8bfde5226163 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 cfe85995df69b..7ff020d6818e1 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 63523cd3a6f6a..b4a2e92cc1262 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -48,7 +48,7 @@ mod rustrt { } } -#[cfg(unix, not(target_os = "macos"))] +#[cfg(unix, not(target_os = "macos"), not(target_os = "ios"))] mod imp { use libc::{c_int, timespec}; @@ -63,6 +63,7 @@ mod imp { } #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] mod imp { use libc::{timeval, timezone, c_int, mach_timebase_info}; @@ -123,6 +124,7 @@ pub fn get_time() -> Timespec { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] unsafe fn os_get_time() -> (i64, i32) { use std::ptr; let mut tv = libc::timeval { tv_sec: 0, tv_usec: 0 }; @@ -130,7 +132,7 @@ pub fn get_time() -> Timespec { (tv.tv_sec as i64, tv.tv_usec * 1000) } - #[cfg(not(target_os = "macos"), not(windows))] + #[cfg(not(target_os = "macos"), not(target_os = "ios"), not(windows))] unsafe fn os_get_time() -> (i64, i32) { let mut tv = libc::timespec { tv_sec: 0, tv_nsec: 0 }; imp::clock_gettime(libc::CLOCK_REALTIME, &mut tv); @@ -162,6 +164,7 @@ pub fn precise_time_ns() -> u64 { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] fn os_precise_time_ns() -> u64 { static mut TIMEBASE: libc::mach_timebase_info = libc::mach_timebase_info { numer: 0, denom: 0 }; @@ -175,7 +178,7 @@ pub fn precise_time_ns() -> u64 { } } - #[cfg(not(windows), not(target_os = "macos"))] + #[cfg(not(windows), not(target_os = "macos"), not(target_os = "ios"))] fn os_precise_time_ns() -> u64 { let mut ts = libc::timespec { tv_sec: 0, tv_nsec: 0 }; unsafe { diff --git a/src/rt/arch/arm/_context.S b/src/rt/arch/arm/_context.S index fb6db57414a56..38fc4827f5861 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 219f0962d771c..0b9012cc2a80a 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 cce14ed5a3ecf..d0e9b81b95a9b 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