auto merge of #14715 : vhbit/rust/ios-pr2, r=alexcrichton

This commit is contained in:
bors 2014-06-16 06:32:03 +00:00
commit 2ef910f71a
50 changed files with 803 additions and 229 deletions

View File

@ -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)

View File

@ -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

@ -1 +1 @@
Subproject commit ed112ca1e4275e1c5707a898f2bf6164707ba378
Subproject commit 7b97b8468f0614072cf3299fa8c51e85f609316f

@ -1 +1 @@
Subproject commit 6a96910f2eaea6d2c705bb12379b23576b30d7d5
Subproject commit 024c67ad651e1a3ca228936c4cfb13a37329baf2

View File

@ -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};

View File

@ -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,

View File

@ -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) })
}

View File

@ -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")]

View File

@ -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(())
}

View File

@ -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 }

View File

@ -93,7 +93,20 @@ pub fn now() -> u64 {
}
}
fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
// Note: although the last parameter isn't used there is no way now to
// convert it to unit type, because LLVM dies in SjLj preparation
// step (unfortunately iOS uses SjLJ exceptions)
//
// It's definitely a temporary workaround just to get it working.
// So far it looks like an LLVM issue and it was reported:
// http://llvm.org/bugs/show_bug.cgi?id=19855
// Actually this issue is pretty common while compiling for armv7 iOS
// and in most cases it is simply solved by using --opt-level=2 (or -O)
//
// For this specific case unfortunately turning optimizations wasn't
// enough.
fn helper(input: libc::c_int, messages: Receiver<Req>, _: int) {
let mut set: c::fd_set = unsafe { mem::zeroed() };
let mut fd = FileDesc::new(input, true);
@ -202,7 +215,9 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
impl Timer {
pub fn new() -> IoResult<Timer> {
unsafe { HELPER.boot(|| {}, helper); }
// See notes above regarding using int return value
// instead of ()
unsafe { HELPER.boot(|| {0}, helper); }
static mut ID: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
let id = unsafe { ID.fetch_add(1, atomics::Relaxed) };

View File

@ -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\

View File

@ -114,6 +114,13 @@ pub mod write {
// which are *far* more efficient. This is obviously undesirable in some
// cases, so if any sort of target feature is specified we don't append v7
// to the feature list.
//
// On iOS only armv7 and newer are supported. So it is useful to
// get all hardware potential via VFP3 (hardware floating point)
// and NEON (SIMD) instructions supported by LLVM.
// Note that without those flags various linking errors might
// arise as some of intrinsicts are converted into function calls
// and nobody provides implementations those functions
fn target_feature<'a>(sess: &'a Session) -> &'a str {
match sess.targ_cfg.os {
abi::OsAndroid => {
@ -122,7 +129,10 @@ pub mod write {
} else {
sess.opts.cg.target_feature.as_slice()
}
}
},
abi::OsiOS if sess.targ_cfg.arch == abi::Arm => {
"+v7,+thumb2,+vfp3,+neon"
},
_ => sess.opts.cg.target_feature.as_slice()
}
}
@ -796,6 +806,10 @@ pub fn link_binary(sess: &Session,
id: &CrateId) -> Vec<Path> {
let mut out_filenames = Vec::new();
for &crate_type in sess.crate_types.borrow().iter() {
if invalid_output_for_target(sess, crate_type) {
sess.bug(format!("invalid output type `{}` for target os `{}`",
crate_type, sess.targ_cfg.os).as_slice());
}
let out_file = link_binary_output(sess, trans, crate_type, outputs, id);
out_filenames.push(out_file);
}
@ -812,6 +826,32 @@ pub fn link_binary(sess: &Session,
out_filenames
}
/// Returns default crate type for target
///
/// Default crate type is used when crate type isn't provided neither
/// through cmd line arguments nor through crate attributes
///
/// It is CrateTypeExecutable for all platforms but iOS as there is no
/// way to run iOS binaries anyway without jailbreaking and
/// interaction with Rust code through static library is the only
/// option for now
pub fn default_output_for_target(sess: &Session) -> config::CrateType {
match sess.targ_cfg.os {
abi::OsiOS => config::CrateTypeStaticlib,
_ => config::CrateTypeExecutable
}
}
/// Checks if target supports crate_type as output
pub fn invalid_output_for_target(sess: &Session,
crate_type: config::CrateType) -> bool {
match (sess.targ_cfg.os, crate_type) {
(abi::OsiOS, config::CrateTypeDylib) => true,
_ => false
}
}
fn is_writeable(p: &Path) -> bool {
match p.stat() {
Err(..) => true,
@ -833,8 +873,11 @@ pub fn filename_for_input(sess: &Session, crate_type: config::CrateType,
abi::OsLinux => (loader::LINUX_DLL_PREFIX, loader::LINUX_DLL_SUFFIX),
abi::OsAndroid => (loader::ANDROID_DLL_PREFIX, loader::ANDROID_DLL_SUFFIX),
abi::OsFreebsd => (loader::FREEBSD_DLL_PREFIX, loader::FREEBSD_DLL_SUFFIX),
abi::OsiOS => unreachable!(),
};
out_filename.with_filename(format!("{}{}{}", prefix, libname,
out_filename.with_filename(format!("{}{}{}",
prefix,
libname,
suffix))
}
config::CrateTypeStaticlib => {
@ -991,7 +1034,7 @@ fn link_rlib<'a>(sess: &'a Session,
// symbol table of the archive. This currently dies on OSX (see
// #11162), and isn't necessary there anyway
match sess.targ_cfg.os {
abi::OsMacos => {}
abi::OsMacos | abi::OsiOS => {}
_ => { a.update_symbols(); }
}
}
@ -1104,15 +1147,16 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
// On OSX, debuggers need this utility to get run to do some munging of
// the symbols
if sess.targ_cfg.os == abi::OsMacos && (sess.opts.debuginfo != NoDebugInfo) {
match Command::new("dsymutil").arg(out_filename).status() {
Ok(..) => {}
Err(e) => {
sess.err(format!("failed to run dsymutil: {}", e).as_slice());
sess.abort_if_errors();
if (sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS)
&& (sess.opts.debuginfo != NoDebugInfo) {
match Command::new("dsymutil").arg(out_filename).status() {
Ok(..) => {}
Err(e) => {
sess.err(format!("failed to run dsymutil: {}", e).as_slice());
sess.abort_if_errors();
}
}
}
}
}
fn link_args(cmd: &mut Command,
@ -1169,7 +1213,7 @@ fn link_args(cmd: &mut Command,
// already done the best it can do, and we also don't want to eliminate the
// metadata. If we're building an executable, however, --gc-sections drops
// the size of hello world from 1.8MB to 597K, a 67% reduction.
if !dylib && sess.targ_cfg.os != abi::OsMacos {
if !dylib && sess.targ_cfg.os != abi::OsMacos && sess.targ_cfg.os != abi::OsiOS {
cmd.arg("-Wl,--gc-sections");
}
@ -1185,7 +1229,7 @@ fn link_args(cmd: &mut Command,
sess.opts.optimize == config::Aggressive {
cmd.arg("-Wl,-O1");
}
} else if sess.targ_cfg.os == abi::OsMacos {
} else if sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS {
// The dead_strip option to the linker specifies that functions and data
// unreachable by the entry point will be removed. This is quite useful
// with Rust's compilation model of compiling libraries at a time into
@ -1348,7 +1392,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
// For those that support this, we ensure we pass the option if the library
// was flagged "static" (most defaults are dynamic) to ensure that if
// libfoo.a and libfoo.so both exist that the right one is chosen.
let takes_hints = sess.targ_cfg.os != abi::OsMacos;
let takes_hints = sess.targ_cfg.os != abi::OsMacos && sess.targ_cfg.os != abi::OsiOS;
for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() {
match kind {

View File

@ -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\

View File

@ -122,7 +122,7 @@ pub fn get_rpath_relative_to_output(os: abi::Os,
abi::OsAndroid | abi::OsLinux | abi::OsFreebsd
=> "$ORIGIN",
abi::OsMacos => "@loader_path",
abi::OsWin32 => unreachable!()
abi::OsWin32 | abi::OsiOS => unreachable!()
};
let mut lib = fs::realpath(&os::make_absolute(lib)).unwrap();

View File

@ -12,7 +12,6 @@
pub struct t {
pub module_asm: String,
pub meta_sect_name: String,
pub data_layout: String,
pub target_triple: String,
pub cc_args: Vec<String> ,

View File

@ -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()
}

View File

@ -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-\

View File

@ -19,7 +19,6 @@ use back;
use back::link;
use back::target_strs;
use back::{arm, x86, x86_64, mips};
use metadata;
use middle::lint;
use syntax::abi;
@ -36,6 +35,7 @@ use getopts::{optopt, optmulti, optflag, optflagopt};
use getopts;
use lib::llvm::llvm;
use std::cell::{RefCell};
use std::fmt;
pub struct Config {
@ -357,18 +357,6 @@ pub fn default_lib_output() -> CrateType {
CrateTypeRlib
}
pub fn cfg_os_to_meta_os(os: abi::Os) -> metadata::loader::Os {
use metadata::loader;
match os {
abi::OsWin32 => loader::OsWin32,
abi::OsLinux => loader::OsLinux,
abi::OsAndroid => loader::OsAndroid,
abi::OsMacos => loader::OsMacos,
abi::OsFreebsd => loader::OsFreebsd
}
}
pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
let tos = match sess.targ_cfg.os {
abi::OsWin32 => InternedString::new("win32"),
@ -376,6 +364,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
abi::OsLinux => InternedString::new("linux"),
abi::OsAndroid => InternedString::new("android"),
abi::OsFreebsd => InternedString::new("freebsd"),
abi::OsiOS => InternedString::new("ios"),
};
// ARM is bi-endian, however using NDK seems to default
@ -441,7 +430,8 @@ static os_names : &'static [(&'static str, abi::Os)] = &'static [
("darwin", abi::OsMacos),
("android", abi::OsAndroid),
("linux", abi::OsLinux),
("freebsd", abi::OsFreebsd)];
("freebsd", abi::OsFreebsd),
("ios", abi::OsiOS)];
pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
for &(arch, abi) in architecture_abis.iter() {
@ -775,6 +765,16 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
}
}
impl fmt::Show for CrateType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CrateTypeExecutable => "bin".fmt(f),
CrateTypeDylib => "dylib".fmt(f),
CrateTypeRlib => "rlib".fmt(f),
CrateTypeStaticlib => "staticlib".fmt(f)
}
}
}
#[cfg(test)]
mod test {

View File

@ -794,17 +794,26 @@ pub fn collect_crate_types(session: &Session,
// command line, then reuse the empty `base` Vec to hold the types that
// will be found in crate attributes.
let mut base = session.opts.crate_types.clone();
if base.len() > 0 {
return base
} else {
if base.len() == 0 {
base.extend(attr_types.move_iter());
if base.len() == 0 {
base.push(config::CrateTypeExecutable);
base.push(link::default_output_for_target(session));
}
base.as_mut_slice().sort();
base.dedup();
return base;
}
base.move_iter().filter(|crate_type| {
let res = !link::invalid_output_for_target(session, *crate_type);
if !res {
session.warn(format!("dropping unsupported crate type `{}` \
for target os `{}`",
*crate_type, session.targ_cfg.os).as_slice());
}
res
}).collect()
}
pub struct OutputFilenames {

View File

@ -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

View File

@ -250,4 +250,3 @@ pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> String)
-> T {
diagnostic::expect(sess.diagnostic(), opt, msg)
}

View File

@ -215,7 +215,8 @@ fn visit_item(e: &Env, i: &ast::Item) {
Some(k) => {
if k.equiv(&("static")) {
cstore::NativeStatic
} else if e.sess.targ_cfg.os == abi::OsMacos &&
} else if (e.sess.targ_cfg.os == abi::OsMacos ||
e.sess.targ_cfg.os == abi::OsiOS) &&
k.equiv(&("framework")) {
cstore::NativeFramework
} else if k.equiv(&("framework")) {
@ -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() {

View File

@ -18,6 +18,7 @@ use metadata::cstore::{MetadataBlob, MetadataVec, MetadataArchive};
use metadata::decoder;
use metadata::encoder;
use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
use syntax::abi;
use syntax::codemap::Span;
use syntax::diagnostic::SpanHandler;
use syntax::crateid::CrateId;
@ -51,14 +52,6 @@ pub static FREEBSD_DLL_SUFFIX: &'static str = ".so";
pub static ANDROID_DLL_PREFIX: &'static str = "lib";
pub static ANDROID_DLL_SUFFIX: &'static str = ".so";
pub enum Os {
OsMacos,
OsWin32,
OsLinux,
OsAndroid,
OsFreebsd
}
pub struct CrateMismatch {
path: Path,
got: String,
@ -72,7 +65,7 @@ pub struct Context<'a> {
pub id_hash: &'a str,
pub hash: Option<&'a Svh>,
pub triple: &'a str,
pub os: Os,
pub os: abi::Os,
pub filesearch: FileSearch<'a>,
pub root: &'a Option<CratePaths>,
pub rejected_via_hash: Vec<CrateMismatch>,
@ -183,10 +176,12 @@ impl<'a> Context<'a> {
}
fn find_library_crate(&mut self) -> Option<Library> {
let (dyprefix, dysuffix) = self.dylibname();
let dypair = self.dylibname();
// want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
let dylib_prefix = format!("{}{}-", dyprefix, self.crate_id.name);
let dylib_prefix = dypair.map(|(prefix, _)| {
format!("{}{}-", prefix, self.crate_id.name)
});
let rlib_prefix = format!("lib{}-", self.crate_id.name);
let mut candidates = HashMap::new();
@ -227,12 +222,14 @@ impl<'a> Context<'a> {
FileDoesntMatch
}
}
} else if file.starts_with(dylib_prefix.as_slice()) &&
file.ends_with(dysuffix){
} else if dypair.map_or(false, |(_, suffix)| {
file.starts_with(dylib_prefix.get_ref().as_slice()) &&
file.ends_with(suffix)
}) {
let (_, suffix) = dypair.unwrap();
let dylib_prefix = dylib_prefix.get_ref().as_slice();
info!("dylib candidate: {}", path.display());
match self.try_match(file,
dylib_prefix.as_slice(),
dysuffix) {
match self.try_match(file, dylib_prefix, suffix) {
Some(hash) => {
info!("dylib accepted, hash: {}", hash);
let slot = candidates.find_or_insert_with(hash, |_| {
@ -457,13 +454,14 @@ impl<'a> Context<'a> {
// Returns the corresponding (prefix, suffix) that files need to have for
// dynamic libraries
fn dylibname(&self) -> (&'static str, &'static str) {
fn dylibname(&self) -> Option<(&'static str, &'static str)> {
match self.os {
OsWin32 => (WIN32_DLL_PREFIX, WIN32_DLL_SUFFIX),
OsMacos => (MACOS_DLL_PREFIX, MACOS_DLL_SUFFIX),
OsLinux => (LINUX_DLL_PREFIX, LINUX_DLL_SUFFIX),
OsAndroid => (ANDROID_DLL_PREFIX, ANDROID_DLL_SUFFIX),
OsFreebsd => (FREEBSD_DLL_PREFIX, FREEBSD_DLL_SUFFIX),
abi::OsWin32 => Some((WIN32_DLL_PREFIX, WIN32_DLL_SUFFIX)),
abi::OsMacos => Some((MACOS_DLL_PREFIX, MACOS_DLL_SUFFIX)),
abi::OsLinux => Some((LINUX_DLL_PREFIX, LINUX_DLL_SUFFIX)),
abi::OsAndroid => Some((ANDROID_DLL_PREFIX, ANDROID_DLL_SUFFIX)),
abi::OsFreebsd => Some((FREEBSD_DLL_PREFIX, FREEBSD_DLL_SUFFIX)),
abi::OsiOS => None,
}
}
@ -505,7 +503,7 @@ impl ArchiveMetadata {
}
// Just a small wrapper to time how long reading metadata takes.
fn get_metadata_section(os: Os, filename: &Path) -> Result<MetadataBlob, String> {
fn get_metadata_section(os: abi::Os, filename: &Path) -> Result<MetadataBlob, String> {
let start = time::precise_time_ns();
let ret = get_metadata_section_imp(os, filename);
info!("reading {} => {}ms", filename.filename_display(),
@ -513,7 +511,7 @@ fn get_metadata_section(os: Os, filename: &Path) -> Result<MetadataBlob, String>
return ret;
}
fn get_metadata_section_imp(os: Os, filename: &Path) -> Result<MetadataBlob, String> {
fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result<MetadataBlob, String> {
if !filename.exists() {
return Err(format!("no such file: '{}'", filename.display()));
}
@ -599,28 +597,30 @@ fn get_metadata_section_imp(os: Os, filename: &Path) -> Result<MetadataBlob, Str
}
}
pub fn meta_section_name(os: Os) -> &'static str {
pub fn meta_section_name(os: abi::Os) -> Option<&'static str> {
match os {
OsMacos => "__DATA,__note.rustc",
OsWin32 => ".note.rustc",
OsLinux => ".note.rustc",
OsAndroid => ".note.rustc",
OsFreebsd => ".note.rustc"
abi::OsMacos => Some("__DATA,__note.rustc"),
abi::OsiOS => Some("__DATA,__note.rustc"),
abi::OsWin32 => Some(".note.rustc"),
abi::OsLinux => Some(".note.rustc"),
abi::OsAndroid => Some(".note.rustc"),
abi::OsFreebsd => Some(".note.rustc")
}
}
pub fn read_meta_section_name(os: Os) -> &'static str {
pub fn read_meta_section_name(os: abi::Os) -> &'static str {
match os {
OsMacos => "__note.rustc",
OsWin32 => ".note.rustc",
OsLinux => ".note.rustc",
OsAndroid => ".note.rustc",
OsFreebsd => ".note.rustc"
abi::OsMacos => "__note.rustc",
abi::OsiOS => unreachable!(),
abi::OsWin32 => ".note.rustc",
abi::OsLinux => ".note.rustc",
abi::OsAndroid => ".note.rustc",
abi::OsFreebsd => ".note.rustc"
}
}
// A diagnostic function for dumping crate metadata to an output stream
pub fn list_file_metadata(os: Os, path: &Path,
pub fn list_file_metadata(os: abi::Os, path: &Path,
out: &mut io::Writer) -> io::IoResult<()> {
match get_metadata_section(os, path) {
Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out),

View File

@ -35,7 +35,7 @@ use driver::driver::{CrateAnalysis, CrateTranslation};
use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
use lib::llvm::{llvm, Vector};
use lib;
use metadata::{csearch, encoder};
use metadata::{csearch, encoder, loader};
use middle::lint;
use middle::astencode;
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
@ -173,12 +173,12 @@ impl<'a> Drop for StatRecorder<'a> {
}
// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv,
fn decl_fn(ccx: &CrateContext, name: &str, cc: lib::llvm::CallConv,
ty: Type, output: ty::t) -> ValueRef {
let llfn: ValueRef = name.with_c_str(|buf| {
unsafe {
llvm::LLVMGetOrInsertFunction(llmod, buf, ty.to_ref())
llvm::LLVMGetOrInsertFunction(ccx.llmod, buf, ty.to_ref())
}
});
@ -197,17 +197,20 @@ fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv,
lib::llvm::SetFunctionCallConv(llfn, cc);
// Function addresses in Rust are never significant, allowing functions to be merged.
lib::llvm::SetUnnamedAddr(llfn, true);
set_split_stack(llfn);
if ccx.is_split_stack_supported() {
set_split_stack(llfn);
}
llfn
}
// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
pub fn decl_cdecl_fn(llmod: ModuleRef,
pub fn decl_cdecl_fn(ccx: &CrateContext,
name: &str,
ty: Type,
output: ty::t) -> ValueRef {
decl_fn(llmod, name, lib::llvm::CCallConv, ty, output)
decl_fn(ccx, name, lib::llvm::CCallConv, ty, output)
}
// only use this for foreign function ABIs and glue, use `get_extern_rust_fn` for Rust functions
@ -222,7 +225,7 @@ pub fn get_extern_fn(ccx: &CrateContext,
Some(n) => return *n,
None => {}
}
let f = decl_fn(ccx.llmod, name, cc, ty, output);
let f = decl_fn(ccx, name, cc, ty, output);
externs.insert(name.to_string(), f);
f
}
@ -251,7 +254,7 @@ pub fn decl_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str) -> ValueRef {
};
let llfty = type_of_rust_fn(ccx, has_env, inputs.as_slice(), output);
let llfn = decl_fn(ccx.llmod, name, lib::llvm::CCallConv, llfty, output);
let llfn = decl_fn(ccx, name, lib::llvm::CCallConv, llfty, output);
let attrs = get_fn_llvm_attributes(ccx, fn_ty);
for &(idx, attr) in attrs.iter() {
unsafe {
@ -1878,7 +1881,7 @@ pub fn register_fn_llvmty(ccx: &CrateContext,
llfty: Type) -> ValueRef {
debug!("register_fn_llvmty id={} sym={}", node_id, sym);
let llfn = decl_fn(ccx.llmod, sym.as_slice(), cc, llfty, ty::mk_nil());
let llfn = decl_fn(ccx, sym.as_slice(), cc, llfty, ty::mk_nil());
finish_register_fn(ccx, sp, sym, node_id, llfn);
llfn
}
@ -1910,7 +1913,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
let llfty = Type::func([ccx.int_type, Type::i8p(ccx).ptr_to()],
&ccx.int_type);
let llfn = decl_cdecl_fn(ccx.llmod, "main", llfty, ty::mk_nil());
let llfn = decl_cdecl_fn(ccx, "main", llfty, ty::mk_nil());
let llbb = "top".with_c_str(|buf| {
unsafe {
llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf)
@ -2279,12 +2282,8 @@ pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec<u8> {
});
unsafe {
llvm::LLVMSetInitializer(llglobal, llconst);
cx.sess()
.targ_cfg
.target_strs
.meta_sect_name
.as_slice()
.with_c_str(|buf| {
let name = loader::meta_section_name(cx.sess().targ_cfg.os);
name.unwrap_or("rust_metadata").with_c_str(|buf| {
llvm::LLVMSetSection(llglobal, buf)
});
}

View File

@ -9,7 +9,7 @@
// except according to those terms.
use syntax::abi::{OsWin32, OsMacos};
use syntax::abi::{OsWin32, OsMacos, OsiOS};
use lib::llvm::*;
use super::cabi::*;
use super::common::*;
@ -36,7 +36,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
enum Strategy { RetValue(Type), RetPointer }
let strategy = match ccx.sess().targ_cfg.os {
OsWin32 | OsMacos => {
OsWin32 | OsMacos | OsiOS => {
match llsize_of_alloc(ccx, rty) {
1 => RetValue(Type::i8(ccx)),
2 => RetValue(Type::i16(ccx)),

View File

@ -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());

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use driver::config::NoDebugInfo;
use driver::session::Session;
use lib::llvm::{ContextRef, ModuleRef, ValueRef};
@ -32,6 +31,7 @@ use std::c_str::ToCStr;
use std::ptr;
use std::rc::Rc;
use std::collections::{HashMap, HashSet};
use syntax::abi;
use syntax::ast;
use syntax::parse::token::InternedString;
@ -273,20 +273,32 @@ impl CrateContext {
None => fail!()
}
}
// Although there is an experimental implementation of LLVM which
// supports SS on armv7 it wasn't approved by Apple, see:
// http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140505/216350.html
// It looks like it might be never accepted to upstream LLVM.
//
// So far the decision was to disable them in default builds
// but it could be enabled (with patched LLVM)
pub fn is_split_stack_supported(&self) -> bool {
let ref cfg = self.sess().targ_cfg;
cfg.os != abi::OsiOS || cfg.arch != abi::Arm
}
}
fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef> {
macro_rules! ifn (
($name:expr fn() -> $ret:expr) => (
if *key == $name {
let f = base::decl_cdecl_fn(ccx.llmod, $name, Type::func([], &$ret), ty::mk_nil());
let f = base::decl_cdecl_fn(ccx, $name, Type::func([], &$ret), ty::mk_nil());
ccx.intrinsics.borrow_mut().insert($name, f.clone());
return Some(f);
}
);
($name:expr fn($($arg:expr),*) -> $ret:expr) => (
if *key == $name {
let f = base::decl_cdecl_fn(ccx.llmod, $name,
let f = base::decl_cdecl_fn(ccx, $name,
Type::func([$($arg),*], &$ret), ty::mk_nil());
ccx.intrinsics.borrow_mut().insert($name, f.clone());
return Some(f);
@ -418,7 +430,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
// The `if key == $name` is already in ifn!
ifn!($name fn($($arg),*) -> $ret);
} else if *key == $name {
let f = base::decl_cdecl_fn(ccx.llmod, stringify!($cname),
let f = base::decl_cdecl_fn(ccx, stringify!($cname),
Type::func([$($arg),*], &$ret),
ty::mk_nil());
ccx.intrinsics.borrow_mut().insert($name, f.clone());

View File

@ -660,7 +660,8 @@ pub fn finalize(cx: &CrateContext) {
// instruct LLVM to emit an older version of dwarf, however,
// for OS X to understand. For more info see #11352
// This can be overridden using --llvm-opts -dwarf-version,N.
if cx.sess().targ_cfg.os == abi::OsMacos {
if cx.sess().targ_cfg.os == abi::OsMacos ||
cx.sess().targ_cfg.os == abi::OsiOS {
"Dwarf Version".with_c_str(
|s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2));
} else {

View File

@ -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;
}

View File

@ -64,6 +64,7 @@ mod imp {
}
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
mod os {
use libc;

View File

@ -145,6 +145,7 @@ mod imp {
}
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
#[cfg(target_os = "win32")]
mod imp {
use core::prelude::*;

View File

@ -156,7 +156,7 @@ pub unsafe fn cleanup() {
pub mod shouldnt_be_public {
#[cfg(not(test))]
pub use super::local_ptr::native::maybe_tls_key;
#[cfg(not(windows), not(target_os = "android"))]
#[cfg(not(windows), not(target_os = "android"), not(target_os = "ios"))]
pub use super::local_ptr::compiled::RT_TLS_PTR;
}

View File

@ -17,6 +17,7 @@
use libc;
#[cfg(not(target_arch = "arm"))]
#[cfg(target_os = "ios")]
#[repr(C)]
pub enum _Unwind_Action {
_UA_SEARCH_PHASE = 1,
@ -61,9 +62,12 @@ pub 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)
}

View File

@ -24,10 +24,11 @@ use alloc::owned::Box;
#[cfg(windows)] // mingw-w32 doesn't like thread_local things
#[cfg(target_os = "android")] // see #10686
#[cfg(target_os = "ios")]
pub use self::native::{init, cleanup, put, take, try_take, unsafe_take, exists,
unsafe_borrow, try_unsafe_borrow};
#[cfg(not(windows), not(target_os = "android"))]
#[cfg(not(windows), not(target_os = "android"), not(target_os = "ios"))]
pub use self::compiled::{init, cleanup, put, take, try_take, unsafe_take, exists,
unsafe_borrow, try_unsafe_borrow};
@ -81,7 +82,7 @@ pub unsafe fn borrow<T>() -> Borrowed<T> {
/// implemented using LLVM's thread_local attribute which isn't necessarily
/// working on all platforms. This implementation is faster, however, so we use
/// it wherever possible.
#[cfg(not(windows), not(target_os = "android"))]
#[cfg(not(windows), not(target_os = "android"), not(target_os = "ios"))]
pub mod compiled {
use core::prelude::*;

View File

@ -361,6 +361,7 @@ mod imp {
}
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
mod os {
use libc;
@ -372,6 +373,10 @@ mod imp {
static __PTHREAD_MUTEX_SIZE__: uint = 40;
#[cfg(target_arch = "x86")]
static __PTHREAD_COND_SIZE__: uint = 24;
#[cfg(target_arch = "arm")]
static __PTHREAD_MUTEX_SIZE__: uint = 40;
#[cfg(target_arch = "arm")]
static __PTHREAD_COND_SIZE__: uint = 24;
static _PTHREAD_MUTEX_SIG_init: libc::c_long = 0x32AAABA7;
static _PTHREAD_COND_SIG_init: libc::c_long = 0x3CB0B1BB;

View File

@ -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
}
}

View File

@ -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());
}
}

View File

@ -37,13 +37,14 @@ pub unsafe fn destroy(key: Key) {
assert!(pthread_key_delete(key) == 0);
}
#[cfg(target_os="macos")]
#[cfg(target_os = "macos")]
#[allow(non_camel_case_types)] // foreign type
type pthread_key_t = ::libc::c_ulong;
#[cfg(target_os="linux")]
#[cfg(target_os="freebsd")]
#[cfg(target_os="android")]
#[cfg(target_os = "ios")]
#[allow(non_camel_case_types)] // foreign type
type pthread_key_t = ::libc::c_uint;

View File

@ -283,16 +283,73 @@ pub mod eabi {
}
else { // cleanup phase
unsafe {
__gcc_personality_v0(version, actions, exception_class, ue_header,
__gcc_personality_v0(version, actions, exception_class, ue_header,
context)
}
}
}
}
// iOS on armv7 is using SjLj exceptions and therefore requires to use
// a specialized personality routine: __gcc_personality_sj0
#[cfg(target_os = "ios", target_arch = "arm", not(test))]
#[doc(hidden)]
#[allow(visible_private_types)]
pub mod eabi {
use uw = libunwind;
use libc::c_int;
extern "C" {
fn __gcc_personality_sj0(version: c_int,
actions: uw::_Unwind_Action,
exception_class: uw::_Unwind_Exception_Class,
ue_header: *uw::_Unwind_Exception,
context: *uw::_Unwind_Context)
-> uw::_Unwind_Reason_Code;
}
#[lang="eh_personality"]
#[no_mangle] // so we can reference it by name from middle/trans/base.rs
pub extern "C" fn rust_eh_personality(
version: c_int,
actions: uw::_Unwind_Action,
exception_class: uw::_Unwind_Exception_Class,
ue_header: *uw::_Unwind_Exception,
context: *uw::_Unwind_Context
) -> uw::_Unwind_Reason_Code
{
unsafe {
__gcc_personality_sj0(version, actions, exception_class, ue_header,
context)
}
}
#[no_mangle] // referenced from rust_try.ll
pub extern "C" fn rust_eh_personality_catch(
version: c_int,
actions: uw::_Unwind_Action,
exception_class: uw::_Unwind_Exception_Class,
ue_header: *uw::_Unwind_Exception,
context: *uw::_Unwind_Context
) -> uw::_Unwind_Reason_Code
{
if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
uw::_URC_HANDLER_FOUND // catch!
}
else { // cleanup phase
unsafe {
__gcc_personality_sj0(version, actions, exception_class, ue_header,
context)
}
}
}
}
// ARM EHABI uses a slightly different personality routine signature,
// but otherwise works the same.
#[cfg(target_arch = "arm", not(test))]
#[cfg(target_arch = "arm", not(test), not(target_os = "ios"))]
#[allow(visible_private_types)]
pub mod eabi {
use uw = libunwind;
@ -330,7 +387,7 @@ pub mod eabi {
}
else { // cleanup phase
unsafe {
__gcc_personality_v0(state, ue_header, context)
__gcc_personality_v0(state, ue_header, context)
}
}
}

View File

@ -153,7 +153,7 @@ impl DynamicLibrary {
}
}
#[cfg(test)]
#[cfg(test, not(target_os = "ios"))]
mod test {
use super::*;
use prelude::*;
@ -206,6 +206,7 @@ mod test {
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
#[cfg(target_os = "freebsd")]
pub mod dl {
use prelude::*;

View File

@ -552,6 +552,7 @@ pub fn pipe() -> Pipe {
/// Returns the proper dll filename for the given basename of a file
/// as a String.
#[cfg(not(target_os="ios"))]
pub fn dll_filename(base: &str) -> String {
format!("{}{}{}", consts::DLL_PREFIX, base, consts::DLL_SUFFIX)
}
@ -608,6 +609,7 @@ pub fn self_exe_name() -> Option<Path> {
}
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
fn load_self() -> Option<Vec<u8>> {
unsafe {
use libc::funcs::extra::_NSGetExecutablePath;
@ -802,6 +804,7 @@ pub fn change_dir(p: &Path) -> bool {
/// Returns the platform-specific value of errno
pub fn errno() -> int {
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
#[cfg(target_os = "freebsd")]
fn errno_location() -> *c_int {
extern {
@ -850,6 +853,7 @@ pub fn error_string(errnum: uint) -> String {
#[cfg(unix)]
fn strerror(errnum: uint) -> String {
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t)
@ -995,6 +999,64 @@ fn real_args_as_bytes() -> Vec<Vec<u8>> {
}
}
// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
// and use underscores in their names - they're most probably
// are considered private and therefore should be avoided
// Here is another way to get arguments using Objective C
// runtime
//
// In general it looks like:
// res = Vec::new()
// let args = [[NSProcessInfo processInfo] arguments]
// for i in range(0, [args count])
// res.push([args objectAtIndex:i])
// res
#[cfg(target_os = "ios")]
fn real_args_as_bytes() -> Vec<Vec<u8>> {
use c_str::CString;
use iter::range;
use mem;
#[link(name = "objc")]
extern {
fn sel_registerName(name: *libc::c_uchar) -> Sel;
fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId;
fn objc_getClass(class_name: *libc::c_uchar) -> NsId;
}
#[link(name = "Foundation", kind = "framework")]
extern {}
type Sel = *libc::c_void;
type NsId = *libc::c_void;
let mut res = Vec::new();
unsafe {
let processInfoSel = sel_registerName("processInfo\0".as_ptr());
let argumentsSel = sel_registerName("arguments\0".as_ptr());
let utf8Sel = sel_registerName("UTF8String\0".as_ptr());
let countSel = sel_registerName("count\0".as_ptr());
let objectAtSel = sel_registerName("objectAtIndex:\0".as_ptr());
let klass = objc_getClass("NSProcessInfo\0".as_ptr());
let info = objc_msgSend(klass, processInfoSel);
let args = objc_msgSend(info, argumentsSel);
let cnt: int = mem::transmute(objc_msgSend(args, countSel));
for i in range(0, cnt) {
let tmp = objc_msgSend(args, objectAtSel, i);
let utf_c_str: *libc::c_char = mem::transmute(objc_msgSend(tmp, utf8Sel));
let s = CString::new(utf_c_str, false);
if s.is_not_null() {
res.push(Vec::from_slice(s.as_bytes_no_nul()))
}
}
}
res
}
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
@ -1532,6 +1594,25 @@ pub mod consts {
pub static EXE_EXTENSION: &'static str = "";
}
#[cfg(target_os = "ios")]
pub mod consts {
pub use os::arch_consts::ARCH;
pub static FAMILY: &'static str = "unix";
/// A string describing the specific operating system in use: in this
/// case, `ios`.
pub static SYSNAME: &'static str = "ios";
/// Specifies the filename suffix used for executable binaries on this
/// platform: in this case, the empty string.
pub static EXE_SUFFIX: &'static str = "";
/// Specifies the file extension, if any, used for executable binaries
/// on this platform: in this case, the empty string.
pub static EXE_EXTENSION: &'static str = "";
}
#[cfg(target_os = "freebsd")]
pub mod consts {
pub use os::arch_consts::ARCH;

View File

@ -13,7 +13,7 @@
pub use self::imp::OsRng;
#[cfg(unix)]
#[cfg(unix, not(target_os = "ios"))]
mod imp {
use io::{IoResult, File};
use path::Path;
@ -28,7 +28,7 @@ mod imp {
/// `/dev/urandom`.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
///
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
/// This does not block.
#[cfg(unix)]
pub struct OsRng {
@ -58,6 +58,71 @@ mod imp {
}
}
#[cfg(target_os = "ios")]
mod imp {
extern crate libc;
use collections::Collection;
use io::{IoResult};
use kinds::marker;
use mem;
use os;
use rand::Rng;
use result::{Ok};
use self::libc::{c_int, size_t};
use slice::MutableVector;
/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
/// `/dev/urandom`.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
/// This does not block.
pub struct OsRng {
marker: marker::NoCopy
}
struct SecRandom;
static kSecRandomDefault: *SecRandom = 0 as *SecRandom;
#[link(name = "Security", kind = "framework")]
extern "C" {
fn SecRandomCopyBytes(rnd: *SecRandom, count: size_t, bytes: *mut u8) -> c_int;
}
impl OsRng {
/// Create a new `OsRng`.
pub fn new() -> IoResult<OsRng> {
Ok(OsRng {marker: marker::NoCopy} )
}
}
impl Rng for OsRng {
fn next_u32(&mut self) -> u32 {
let mut v = [0u8, .. 4];
self.fill_bytes(v);
unsafe { mem::transmute(v) }
}
fn next_u64(&mut self) -> u64 {
let mut v = [0u8, .. 8];
self.fill_bytes(v);
unsafe { mem::transmute(v) }
}
fn fill_bytes(&mut self, v: &mut [u8]) {
let ret = unsafe {
SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
};
if ret == -1 {
fail!("couldn't generate random bytes: {}", os::last_os_error());
}
}
}
}
#[cfg(windows)]
mod imp {
extern crate libc;

View File

@ -237,22 +237,63 @@ fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> {
#[cfg(unix)]
mod imp {
use c_str::CString;
use io::{IoResult, IoError, Writer};
use io::{IoResult, Writer};
use libc;
use mem;
use option::{Some, None, Option};
use result::{Ok, Err};
use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
struct Context<'a> {
idx: int,
writer: &'a mut Writer,
last_error: Option<IoError>,
/// As always - iOS on arm uses SjLj exceptions and
/// _Unwind_Backtrace is even not available there. Still,
/// backtraces could be extracted using a backtrace function,
/// which thanks god is public
///
/// As mentioned in a huge comment block above, backtrace doesn't
/// play well with green threads, so while it is extremely nice
/// and simple to use it should be used only on iOS devices as the
/// only viable option.
#[cfg(target_os = "ios", target_arch = "arm")]
#[inline(never)]
pub fn write(w: &mut Writer) -> IoResult<()> {
use iter::{Iterator, range};
use result;
use slice::{MutableVector};
extern {
fn backtrace(buf: *mut *libc::c_void, sz: libc::c_int) -> libc::c_int;
}
// while it doesn't requires lock for work as everything is
// local, it still displays much nicier backtraces when a
// couple of tasks fail simultaneously
static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
let _g = unsafe { LOCK.lock() };
try!(writeln!(w, "stack backtrace:"));
// 100 lines should be enough
static SIZE: libc::c_int = 100;
let mut buf: [*libc::c_void, ..SIZE] = unsafe {mem::zeroed()};
let cnt = unsafe { backtrace(buf.as_mut_ptr(), SIZE) as uint};
// skipping the first one as it is write itself
result::fold_(range(1, cnt).map(|i| {
print(w, i as int, buf[i])
}))
}
#[cfg(not(target_os = "ios", target_arch = "arm"))]
#[inline(never)] // if we know this is a function call, we can skip it when
// tracing
pub fn write(w: &mut Writer) -> IoResult<()> {
use io::IoError;
struct Context<'a> {
idx: int,
writer: &'a mut Writer,
last_error: Option<IoError>,
}
// When using libbacktrace, we use some necessary global state, so we
// need to prevent more than one thread from entering this block. This
// is semi-reasonable in terms of printing anyway, and we know that all
@ -291,7 +332,7 @@ mod imp {
// instructions after it. This means that the return instruction
// pointer points *outside* of the calling function, and by
// unwinding it we go back to the original function.
let ip = if cfg!(target_os = "macos") {
let ip = if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
ip
} else {
unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
@ -323,6 +364,7 @@ mod imp {
}
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> {
use intrinsics;
#[repr(C)]
@ -347,7 +389,7 @@ mod imp {
}
}
#[cfg(not(target_os = "macos"))]
#[cfg(not(target_os = "macos"), not(target_os = "ios"))]
fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> {
use collections::Collection;
use iter::Iterator;
@ -487,9 +529,14 @@ mod imp {
/// Unwind library interface used for backtraces
///
/// Note that the native libraries come from librustrt, not this module.
/// Note that the native libraries come from librustrt, not this
/// module.
/// Note that dead code is allowed as here are just bindings
/// iOS doesn't use all of them it but adding more
/// platform-specific configs pollutes the code too much
#[allow(non_camel_case_types)]
#[allow(non_snake_case_functions)]
#[allow(dead_code)]
mod uw {
use libc;
@ -514,6 +561,8 @@ mod imp {
arg: *libc::c_void) -> _Unwind_Reason_Code;
extern {
// No native _Unwind_Backtrace on iOS
#[cfg(not(target_os = "ios", target_arch = "arm"))]
pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
trace_argument: *libc::c_void)
-> _Unwind_Reason_Code;

View File

@ -39,3 +39,7 @@ extern {}
#[cfg(target_os = "macos")]
#[link(name = "System")]
extern {}
#[cfg(target_os = "ios")]
#[link(name = "System")]
extern {}

View File

@ -11,7 +11,7 @@
use std::fmt;
#[deriving(PartialEq)]
pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, }
pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, OsiOS, }
#[deriving(PartialEq, Eq, Hash, Encodable, Decodable, Clone)]
pub enum Abi {
@ -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() {

View File

@ -46,7 +46,7 @@ mod rustrt {
}
}
#[cfg(unix, not(target_os = "macos"))]
#[cfg(unix, not(target_os = "macos"), not(target_os = "ios"))]
mod imp {
use libc::{c_int, timespec};
@ -61,6 +61,7 @@ mod imp {
}
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
mod imp {
use libc::{timeval, timezone, c_int, mach_timebase_info};
@ -121,6 +122,7 @@ pub fn get_time() -> Timespec {
}
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
unsafe fn os_get_time() -> (i64, i32) {
use std::ptr;
let mut tv = libc::timeval { tv_sec: 0, tv_usec: 0 };
@ -128,7 +130,7 @@ pub fn get_time() -> Timespec {
(tv.tv_sec as i64, tv.tv_usec * 1000)
}
#[cfg(not(target_os = "macos"), not(windows))]
#[cfg(not(target_os = "macos"), not(target_os = "ios"), not(windows))]
unsafe fn os_get_time() -> (i64, i32) {
let mut tv = libc::timespec { tv_sec: 0, tv_nsec: 0 };
imp::clock_gettime(libc::CLOCK_REALTIME, &mut tv);
@ -160,6 +162,7 @@ pub fn precise_time_ns() -> u64 {
}
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
fn os_precise_time_ns() -> u64 {
static mut TIMEBASE: libc::mach_timebase_info = libc::mach_timebase_info { numer: 0,
denom: 0 };
@ -173,7 +176,7 @@ pub fn precise_time_ns() -> u64 {
}
}
#[cfg(not(windows), not(target_os = "macos"))]
#[cfg(not(windows), not(target_os = "macos"), not(target_os = "ios"))]
fn os_precise_time_ns() -> u64 {
let mut ts = libc::timespec { tv_sec: 0, tv_nsec: 0 };
unsafe {

View File

@ -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

View File

@ -8,33 +8,63 @@
.text
.code 32
.arm
#if defined(__APPLE__)
.align 2
#else
.align
#endif
.global rust_stack_exhausted
.global __morestack
.hidden __morestack
#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
#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

View File

@ -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
record_sp_limit:
.globl RECORD_SP_LIMIT
.globl GET_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