Basic iOS support
This commit is contained in:
parent
0c10c68682
commit
a49b765f9a
@ -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};
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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) })
|
||||
}
|
||||
|
@ -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")]
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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 }
|
||||
|
@ -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) };
|
||||
|
@ -34,6 +34,14 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
|
||||
-a0:0:64-n32".to_string()
|
||||
}
|
||||
|
||||
abi::OsiOS => {
|
||||
"e-p:32:32:32\
|
||||
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
|
||||
-f32:32:32-f64:64:64\
|
||||
-v64:64:64-v128:64:128\
|
||||
-a0:0:64-n32".to_string()
|
||||
}
|
||||
|
||||
abi::OsWin32 => {
|
||||
"e-p:32:32:32\
|
||||
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
|
||||
|
@ -114,6 +114,13 @@ pub mod write {
|
||||
// which are *far* more efficient. This is obviously undesirable in some
|
||||
// cases, so if any sort of target feature is specified we don't append v7
|
||||
// to the feature list.
|
||||
//
|
||||
// On iOS only armv7 and newer are supported. So it is useful to
|
||||
// get all hardware potential via VFP3 (hardware floating point)
|
||||
// and NEON (SIMD) instructions supported by LLVM.
|
||||
// Note that without those flags various linking errors might
|
||||
// arise as some of intrinsicts are converted into function calls
|
||||
// and nobody provides implementations those functions
|
||||
fn target_feature<'a>(sess: &'a Session) -> &'a str {
|
||||
match sess.targ_cfg.os {
|
||||
abi::OsAndroid => {
|
||||
@ -122,7 +129,10 @@ pub mod write {
|
||||
} else {
|
||||
sess.opts.cg.target_feature.as_slice()
|
||||
}
|
||||
}
|
||||
},
|
||||
abi::OsiOS if sess.targ_cfg.arch == abi::Arm => {
|
||||
"+v7,+thumb2,+vfp3,+neon"
|
||||
},
|
||||
_ => sess.opts.cg.target_feature.as_slice()
|
||||
}
|
||||
}
|
||||
@ -827,15 +837,23 @@ pub fn filename_for_input(sess: &Session, crate_type: config::CrateType,
|
||||
out_filename.with_filename(format!("lib{}.rlib", libname))
|
||||
}
|
||||
config::CrateTypeDylib => {
|
||||
let (prefix, suffix) = match sess.targ_cfg.os {
|
||||
abi::OsWin32 => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX),
|
||||
abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX),
|
||||
abi::OsLinux => (loader::LINUX_DLL_PREFIX, loader::LINUX_DLL_SUFFIX),
|
||||
abi::OsAndroid => (loader::ANDROID_DLL_PREFIX, loader::ANDROID_DLL_SUFFIX),
|
||||
abi::OsFreebsd => (loader::FREEBSD_DLL_PREFIX, loader::FREEBSD_DLL_SUFFIX),
|
||||
};
|
||||
out_filename.with_filename(format!("{}{}{}", prefix, libname,
|
||||
suffix))
|
||||
// There is no support of DyLibs on iOS
|
||||
if sess.targ_cfg.os == abi::OsiOS {
|
||||
out_filename.with_filename(format!("lib{}.a", libname))
|
||||
} else {
|
||||
let (prefix, suffix) = match sess.targ_cfg.os {
|
||||
abi::OsWin32 => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX),
|
||||
abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX),
|
||||
abi::OsLinux => (loader::LINUX_DLL_PREFIX, loader::LINUX_DLL_SUFFIX),
|
||||
abi::OsAndroid => (loader::ANDROID_DLL_PREFIX, loader::ANDROID_DLL_SUFFIX),
|
||||
abi::OsFreebsd => (loader::FREEBSD_DLL_PREFIX, loader::FREEBSD_DLL_SUFFIX),
|
||||
abi::OsiOS => unreachable!(),
|
||||
};
|
||||
out_filename.with_filename(format!("{}{}{}",
|
||||
prefix,
|
||||
libname,
|
||||
suffix))
|
||||
}
|
||||
}
|
||||
config::CrateTypeStaticlib => {
|
||||
out_filename.with_filename(format!("lib{}.a", libname))
|
||||
@ -886,7 +904,14 @@ fn link_binary_output(sess: &Session,
|
||||
link_natively(sess, trans, false, &obj_filename, &out_filename);
|
||||
}
|
||||
config::CrateTypeDylib => {
|
||||
link_natively(sess, trans, true, &obj_filename, &out_filename);
|
||||
if sess.targ_cfg.os == abi::OsiOS {
|
||||
sess.warn(format!("No dylib for iOS -> saving static library {} to {}",
|
||||
obj_filename.display(), out_filename.display()).as_slice());
|
||||
link_staticlib(sess, &obj_filename, &out_filename);
|
||||
}
|
||||
else {
|
||||
link_natively(sess, trans, true, &obj_filename, &out_filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -991,7 +1016,7 @@ fn link_rlib<'a>(sess: &'a Session,
|
||||
// symbol table of the archive. This currently dies on OSX (see
|
||||
// #11162), and isn't necessary there anyway
|
||||
match sess.targ_cfg.os {
|
||||
abi::OsMacos => {}
|
||||
abi::OsMacos | abi::OsiOS => {}
|
||||
_ => { a.update_symbols(); }
|
||||
}
|
||||
}
|
||||
@ -1104,15 +1129,16 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
|
||||
|
||||
// On OSX, debuggers need this utility to get run to do some munging of
|
||||
// the symbols
|
||||
if sess.targ_cfg.os == abi::OsMacos && (sess.opts.debuginfo != NoDebugInfo) {
|
||||
match Command::new("dsymutil").arg(out_filename).status() {
|
||||
Ok(..) => {}
|
||||
Err(e) => {
|
||||
sess.err(format!("failed to run dsymutil: {}", e).as_slice());
|
||||
sess.abort_if_errors();
|
||||
if (sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS)
|
||||
&& (sess.opts.debuginfo != NoDebugInfo) {
|
||||
match Command::new("dsymutil").arg(out_filename).status() {
|
||||
Ok(..) => {}
|
||||
Err(e) => {
|
||||
sess.err(format!("failed to run dsymutil: {}", e).as_slice());
|
||||
sess.abort_if_errors();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn link_args(cmd: &mut Command,
|
||||
@ -1169,7 +1195,7 @@ fn link_args(cmd: &mut Command,
|
||||
// already done the best it can do, and we also don't want to eliminate the
|
||||
// metadata. If we're building an executable, however, --gc-sections drops
|
||||
// the size of hello world from 1.8MB to 597K, a 67% reduction.
|
||||
if !dylib && sess.targ_cfg.os != abi::OsMacos {
|
||||
if !dylib && sess.targ_cfg.os != abi::OsMacos && sess.targ_cfg.os != abi::OsiOS {
|
||||
cmd.arg("-Wl,--gc-sections");
|
||||
}
|
||||
|
||||
@ -1185,7 +1211,7 @@ fn link_args(cmd: &mut Command,
|
||||
sess.opts.optimize == config::Aggressive {
|
||||
cmd.arg("-Wl,-O1");
|
||||
}
|
||||
} else if sess.targ_cfg.os == abi::OsMacos {
|
||||
} else if sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS {
|
||||
// The dead_strip option to the linker specifies that functions and data
|
||||
// unreachable by the entry point will be removed. This is quite useful
|
||||
// with Rust's compilation model of compiling libraries at a time into
|
||||
@ -1348,7 +1374,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
|
||||
// For those that support this, we ensure we pass the option if the library
|
||||
// was flagged "static" (most defaults are dynamic) to ensure that if
|
||||
// libfoo.a and libfoo.so both exist that the right one is chosen.
|
||||
let takes_hints = sess.targ_cfg.os != abi::OsMacos;
|
||||
let takes_hints = sess.targ_cfg.os != abi::OsMacos && sess.targ_cfg.os != abi::OsiOS;
|
||||
|
||||
for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() {
|
||||
match kind {
|
||||
|
@ -29,6 +29,14 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
|
||||
-a0:0:64-n32".to_string()
|
||||
}
|
||||
|
||||
abi::OsiOS => {
|
||||
"E-p:32:32:32\
|
||||
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
|
||||
-f32:32:32-f64:64:64\
|
||||
-v64:64:64-v128:64:128\
|
||||
-a0:0:64-n32".to_string()
|
||||
}
|
||||
|
||||
abi::OsWin32 => {
|
||||
"E-p:32:32:32\
|
||||
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
|
||||
|
@ -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();
|
||||
|
@ -31,6 +31,14 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os)
|
||||
-n8:16:32".to_string()
|
||||
}
|
||||
|
||||
abi::OsiOS => {
|
||||
"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\
|
||||
-i32:32:32-i64:32:64\
|
||||
-f32:32:32-f64:32:64-v64:64:64\
|
||||
-v128:128:128-a0:0:64-f80:128:128\
|
||||
-n8:16:32".to_string()
|
||||
}
|
||||
|
||||
abi::OsWin32 => {
|
||||
"e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32".to_string()
|
||||
}
|
||||
|
@ -28,6 +28,12 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
|
||||
s0:64:64-f80:128:128-n8:16:32:64".to_string()
|
||||
}
|
||||
|
||||
abi::OsiOS => {
|
||||
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
|
||||
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
|
||||
s0:64:64-f80:128:128-n8:16:32:64".to_string()
|
||||
}
|
||||
|
||||
abi::OsWin32 => {
|
||||
// FIXME: Test this. Copied from linux (#2398)
|
||||
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
|
||||
|
@ -362,7 +362,8 @@ pub fn cfg_os_to_meta_os(os: abi::Os) -> metadata::loader::Os {
|
||||
abi::OsLinux => loader::OsLinux,
|
||||
abi::OsAndroid => loader::OsAndroid,
|
||||
abi::OsMacos => loader::OsMacos,
|
||||
abi::OsFreebsd => loader::OsFreebsd
|
||||
abi::OsFreebsd => loader::OsFreebsd,
|
||||
abi::OsiOS => loader::OsiOS,
|
||||
}
|
||||
}
|
||||
|
||||
@ -373,6 +374,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
|
||||
abi::OsLinux => InternedString::new("linux"),
|
||||
abi::OsAndroid => InternedString::new("android"),
|
||||
abi::OsFreebsd => InternedString::new("freebsd"),
|
||||
abi::OsiOS => InternedString::new("ios"),
|
||||
};
|
||||
|
||||
// ARM is bi-endian, however using NDK seems to default
|
||||
@ -438,7 +440,8 @@ static os_names : &'static [(&'static str, abi::Os)] = &'static [
|
||||
("darwin", abi::OsMacos),
|
||||
("android", abi::OsAndroid),
|
||||
("linux", abi::OsLinux),
|
||||
("freebsd", abi::OsFreebsd)];
|
||||
("freebsd", abi::OsFreebsd),
|
||||
("ios", abi::OsiOS)];
|
||||
|
||||
pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
|
||||
for &(arch, abi) in architecture_abis.iter() {
|
||||
|
@ -249,4 +249,3 @@ pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> String)
|
||||
-> T {
|
||||
diagnostic::expect(sess.diagnostic(), opt, msg)
|
||||
}
|
||||
|
||||
|
@ -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")) {
|
||||
|
@ -39,6 +39,9 @@ use time;
|
||||
pub static MACOS_DLL_PREFIX: &'static str = "lib";
|
||||
pub static MACOS_DLL_SUFFIX: &'static str = ".dylib";
|
||||
|
||||
pub static IOS_DLL_PREFIX: &'static str = "lib";
|
||||
pub static IOS_DLL_SUFFIX: &'static str = ".dylib";
|
||||
|
||||
pub static WIN32_DLL_PREFIX: &'static str = "";
|
||||
pub static WIN32_DLL_SUFFIX: &'static str = ".dll";
|
||||
|
||||
@ -56,7 +59,8 @@ pub enum Os {
|
||||
OsWin32,
|
||||
OsLinux,
|
||||
OsAndroid,
|
||||
OsFreebsd
|
||||
OsFreebsd,
|
||||
OsiOS
|
||||
}
|
||||
|
||||
pub struct CrateMismatch {
|
||||
@ -455,6 +459,7 @@ impl<'a> Context<'a> {
|
||||
OsLinux => (LINUX_DLL_PREFIX, LINUX_DLL_SUFFIX),
|
||||
OsAndroid => (ANDROID_DLL_PREFIX, ANDROID_DLL_SUFFIX),
|
||||
OsFreebsd => (FREEBSD_DLL_PREFIX, FREEBSD_DLL_SUFFIX),
|
||||
OsiOS => (IOS_DLL_PREFIX, IOS_DLL_SUFFIX),
|
||||
}
|
||||
}
|
||||
|
||||
@ -593,6 +598,7 @@ fn get_metadata_section_imp(os: Os, filename: &Path) -> Result<MetadataBlob, Str
|
||||
pub fn meta_section_name(os: Os) -> &'static str {
|
||||
match os {
|
||||
OsMacos => "__DATA,__note.rustc",
|
||||
OsiOS => "__DATA,__note.rustc",
|
||||
OsWin32 => ".note.rustc",
|
||||
OsLinux => ".note.rustc",
|
||||
OsAndroid => ".note.rustc",
|
||||
@ -603,6 +609,7 @@ pub fn meta_section_name(os: Os) -> &'static str {
|
||||
pub fn read_meta_section_name(os: Os) -> &'static str {
|
||||
match os {
|
||||
OsMacos => "__note.rustc",
|
||||
OsiOS => "__note.rustc",
|
||||
OsWin32 => ".note.rustc",
|
||||
OsLinux => ".note.rustc",
|
||||
OsAndroid => ".note.rustc",
|
||||
|
@ -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)),
|
||||
|
@ -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());
|
||||
|
@ -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 {
|
||||
|
@ -64,6 +64,7 @@ mod imp {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_os = "ios")]
|
||||
mod os {
|
||||
use libc;
|
||||
|
||||
|
@ -145,6 +145,7 @@ mod imp {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_os = "ios")]
|
||||
#[cfg(target_os = "win32")]
|
||||
mod imp {
|
||||
use core::prelude::*;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
use libc;
|
||||
|
||||
#[cfg(not(target_arch = "arm"))]
|
||||
#[cfg(target_os = "ios")]
|
||||
#[repr(C)]
|
||||
pub enum _Unwind_Action {
|
||||
_UA_SEARCH_PHASE = 1,
|
||||
@ -61,9 +62,12 @@ pub static unwinder_private_data_size: int = 5;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub static unwinder_private_data_size: int = 2;
|
||||
|
||||
#[cfg(target_arch = "arm")]
|
||||
#[cfg(target_arch = "arm", not(target_os = "ios"))]
|
||||
pub static unwinder_private_data_size: int = 20;
|
||||
|
||||
#[cfg(target_arch = "arm", target_os = "ios")]
|
||||
pub static unwinder_private_data_size: int = 5;
|
||||
|
||||
#[cfg(target_arch = "mips")]
|
||||
pub static unwinder_private_data_size: int = 2;
|
||||
|
||||
@ -89,8 +93,27 @@ extern {}
|
||||
#[link(name = "gcc")]
|
||||
extern {}
|
||||
|
||||
|
||||
extern "C" {
|
||||
// iOS on armv7 uses SjLj exceptions and requires to link
|
||||
// agains corresponding routine (..._SjLj_...)
|
||||
// So here we just skip linking for iOS
|
||||
#[cfg(not(target_os = "ios", target_arch = "arm"))]
|
||||
pub fn _Unwind_RaiseException(exception: *_Unwind_Exception)
|
||||
-> _Unwind_Reason_Code;
|
||||
pub fn _Unwind_DeleteException(exception: *_Unwind_Exception);
|
||||
}
|
||||
|
||||
// ... and now we just providing access to SjLj counterspart
|
||||
// through a standard name to hide those details from others
|
||||
// (see also comment above regarding _Unwind_RaiseException)
|
||||
#[cfg(target_os = "ios", target_arch = "arm")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn _Unwind_RaiseException(exc: *_Unwind_Exception)
|
||||
-> _Unwind_Reason_Code {
|
||||
extern "C" {
|
||||
fn _Unwind_SjLj_RaiseException(e: *_Unwind_Exception)
|
||||
-> _Unwind_Reason_Code; }
|
||||
|
||||
_Unwind_SjLj_RaiseException(exc)
|
||||
}
|
||||
|
@ -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::*;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -173,7 +173,8 @@ pub unsafe fn record_sp_limit(limit: uint) {
|
||||
return target_record_sp_limit(limit);
|
||||
|
||||
// x86-64
|
||||
#[cfg(target_arch = "x86_64", target_os = "macos")] #[inline(always)]
|
||||
#[cfg(target_arch = "x86_64", target_os = "macos")]
|
||||
#[cfg(target_arch = "x86_64", target_os = "ios")] #[inline(always)]
|
||||
unsafe fn target_record_sp_limit(limit: uint) {
|
||||
asm!("movq $$0x60+90*8, %rsi
|
||||
movq $0, %gs:(%rsi)" :: "r"(limit) : "rsi" : "volatile")
|
||||
@ -195,7 +196,8 @@ pub unsafe fn record_sp_limit(limit: uint) {
|
||||
}
|
||||
|
||||
// x86
|
||||
#[cfg(target_arch = "x86", target_os = "macos")] #[inline(always)]
|
||||
#[cfg(target_arch = "x86", target_os = "macos")]
|
||||
#[cfg(target_arch = "x86", target_os = "ios")] #[inline(always)]
|
||||
unsafe fn target_record_sp_limit(limit: uint) {
|
||||
asm!("movl $$0x48+90*4, %eax
|
||||
movl $0, %gs:(%eax)" :: "r"(limit) : "eax" : "volatile")
|
||||
@ -243,7 +245,8 @@ pub unsafe fn get_sp_limit() -> uint {
|
||||
return target_get_sp_limit();
|
||||
|
||||
// x86-64
|
||||
#[cfg(target_arch = "x86_64", target_os = "macos")] #[inline(always)]
|
||||
#[cfg(target_arch = "x86_64", target_os = "macos")]
|
||||
#[cfg(target_arch = "x86_64", target_os = "ios")] #[inline(always)]
|
||||
unsafe fn target_get_sp_limit() -> uint {
|
||||
let limit;
|
||||
asm!("movq $$0x60+90*8, %rsi
|
||||
@ -270,7 +273,8 @@ pub unsafe fn get_sp_limit() -> uint {
|
||||
}
|
||||
|
||||
// x86
|
||||
#[cfg(target_arch = "x86", target_os = "macos")] #[inline(always)]
|
||||
#[cfg(target_arch = "x86", target_os = "macos")]
|
||||
#[cfg(target_arch = "x86", target_os = "ios")] #[inline(always)]
|
||||
unsafe fn target_get_sp_limit() -> uint {
|
||||
let limit;
|
||||
asm!("movl $$0x48+90*4, %eax
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -285,16 +285,74 @@ pub mod eabi {
|
||||
}
|
||||
else { // cleanup phase
|
||||
unsafe {
|
||||
__gcc_personality_v0(version, actions, exception_class, ue_header,
|
||||
__gcc_personality_v0(version, actions, exception_class, ue_header,
|
||||
context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iOS on armv7 is using SjLj exceptions and therefore requires to use
|
||||
// a specialized personality routine: __gcc_personality_sj0
|
||||
|
||||
#[cfg(target_os = "ios", target_arch = "arm", not(test))]
|
||||
#[doc(hidden)]
|
||||
#[allow(visible_private_types)]
|
||||
pub mod eabi {
|
||||
use uw = libunwind;
|
||||
use libc::c_int;
|
||||
|
||||
extern "C" {
|
||||
#[cfg(target_os = "ios", target_arch = "arm")]
|
||||
fn __gcc_personality_sj0(version: c_int,
|
||||
actions: uw::_Unwind_Action,
|
||||
exception_class: uw::_Unwind_Exception_Class,
|
||||
ue_header: *uw::_Unwind_Exception,
|
||||
context: *uw::_Unwind_Context)
|
||||
-> uw::_Unwind_Reason_Code;
|
||||
}
|
||||
|
||||
#[lang="eh_personality"]
|
||||
#[no_mangle] // so we can reference it by name from middle/trans/base.rs
|
||||
pub extern "C" fn rust_eh_personality(
|
||||
version: c_int,
|
||||
actions: uw::_Unwind_Action,
|
||||
exception_class: uw::_Unwind_Exception_Class,
|
||||
ue_header: *uw::_Unwind_Exception,
|
||||
context: *uw::_Unwind_Context
|
||||
) -> uw::_Unwind_Reason_Code
|
||||
{
|
||||
unsafe {
|
||||
__gcc_personality_sj0(version, actions, exception_class, ue_header,
|
||||
context)
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle] // referenced from rust_try.ll
|
||||
pub extern "C" fn rust_eh_personality_catch(
|
||||
version: c_int,
|
||||
actions: uw::_Unwind_Action,
|
||||
exception_class: uw::_Unwind_Exception_Class,
|
||||
ue_header: *uw::_Unwind_Exception,
|
||||
context: *uw::_Unwind_Context
|
||||
) -> uw::_Unwind_Reason_Code
|
||||
{
|
||||
if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
|
||||
uw::_URC_HANDLER_FOUND // catch!
|
||||
}
|
||||
else { // cleanup phase
|
||||
unsafe {
|
||||
__gcc_personality_sj0(version, actions, exception_class, ue_header,
|
||||
context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ARM EHABI uses a slightly different personality routine signature,
|
||||
// but otherwise works the same.
|
||||
#[cfg(target_arch = "arm", not(test))]
|
||||
#[cfg(target_arch = "arm", not(test), not(target_os = "ios"))]
|
||||
#[allow(visible_private_types)]
|
||||
pub mod eabi {
|
||||
use uw = libunwind;
|
||||
@ -332,7 +390,7 @@ pub mod eabi {
|
||||
}
|
||||
else { // cleanup phase
|
||||
unsafe {
|
||||
__gcc_personality_v0(state, ue_header, context)
|
||||
__gcc_personality_v0(state, ue_header, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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::*;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -237,22 +237,58 @@ fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> {
|
||||
#[cfg(unix)]
|
||||
mod imp {
|
||||
use c_str::CString;
|
||||
use io::{IoResult, IoError, Writer};
|
||||
use io::{IoResult, Writer};
|
||||
use libc;
|
||||
use mem;
|
||||
use option::{Some, None, Option};
|
||||
use result::{Ok, Err};
|
||||
use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
||||
|
||||
struct Context<'a> {
|
||||
idx: int,
|
||||
writer: &'a mut Writer,
|
||||
last_error: Option<IoError>,
|
||||
/// As always - iOS on arm uses SjLj exceptions and
|
||||
/// _Unwind_Backtrace is even not available there. Still,
|
||||
/// backtraces could be extracted using a backtrace function,
|
||||
/// which thanks god is public
|
||||
#[cfg(target_os = "ios", target_arch = "arm")]
|
||||
#[inline(never)]
|
||||
pub fn write(w: &mut Writer) -> IoResult<()> {
|
||||
use iter::{Iterator, range};
|
||||
use result;
|
||||
use slice::{MutableVector};
|
||||
|
||||
extern {
|
||||
fn backtrace(buf: *mut *libc::c_void, sz: libc::c_int) -> libc::c_int;
|
||||
}
|
||||
|
||||
// while it doesn't requires lock for work as everything is
|
||||
// local, it still displays much nicier backtraces when a
|
||||
// couple of tasks fail simultaneously
|
||||
static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
|
||||
let _g = unsafe { LOCK.lock() };
|
||||
|
||||
try!(writeln!(w, "stack backtrace:"));
|
||||
// 100 lines should be enough
|
||||
static size: libc::c_int = 100;
|
||||
let mut buf: [*libc::c_void, ..size] = unsafe {mem::zeroed()};
|
||||
let cnt = unsafe { backtrace(buf.as_mut_ptr(), size) as uint};
|
||||
|
||||
// skipping the first one as it is write itself
|
||||
result::fold_(range(1, cnt).map(|i| {
|
||||
print(w, i as int, buf[i])
|
||||
}))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "ios", target_arch = "arm"))]
|
||||
#[inline(never)] // if we know this is a function call, we can skip it when
|
||||
// tracing
|
||||
pub fn write(w: &mut Writer) -> IoResult<()> {
|
||||
use io::IoError;
|
||||
|
||||
struct Context<'a> {
|
||||
idx: int,
|
||||
writer: &'a mut Writer,
|
||||
last_error: Option<IoError>,
|
||||
}
|
||||
|
||||
// When using libbacktrace, we use some necessary global state, so we
|
||||
// need to prevent more than one thread from entering this block. This
|
||||
// is semi-reasonable in terms of printing anyway, and we know that all
|
||||
@ -291,7 +327,7 @@ mod imp {
|
||||
// instructions after it. This means that the return instruction
|
||||
// pointer points *outside* of the calling function, and by
|
||||
// unwinding it we go back to the original function.
|
||||
let ip = if cfg!(target_os = "macos") {
|
||||
let ip = if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
|
||||
ip
|
||||
} else {
|
||||
unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
|
||||
@ -323,6 +359,7 @@ mod imp {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_os = "ios")]
|
||||
fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> {
|
||||
use intrinsics;
|
||||
#[repr(C)]
|
||||
@ -347,7 +384,7 @@ mod imp {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
#[cfg(not(target_os = "macos"), not(target_os = "ios"))]
|
||||
fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> {
|
||||
use collections::Collection;
|
||||
use iter::Iterator;
|
||||
@ -487,9 +524,14 @@ mod imp {
|
||||
|
||||
/// Unwind library interface used for backtraces
|
||||
///
|
||||
/// Note that the native libraries come from librustrt, not this module.
|
||||
/// Note that the native libraries come from librustrt, not this
|
||||
/// module.
|
||||
/// Note that dead code is allowed as here are just bindings
|
||||
/// iOS doesn't use all of them it but adding more
|
||||
/// platform-specific configs pollutes the code too much
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(non_snake_case_functions)]
|
||||
#[allow(dead_code)]
|
||||
mod uw {
|
||||
use libc;
|
||||
|
||||
@ -514,6 +556,8 @@ mod imp {
|
||||
arg: *libc::c_void) -> _Unwind_Reason_Code;
|
||||
|
||||
extern {
|
||||
// No native _Unwind_Backtrace on iOS
|
||||
#[cfg(not(target_os = "ios", target_arch = "arm"))]
|
||||
pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
|
||||
trace_argument: *libc::c_void)
|
||||
-> _Unwind_Reason_Code;
|
||||
|
@ -39,3 +39,7 @@ extern {}
|
||||
#[cfg(target_os = "macos")]
|
||||
#[link(name = "System")]
|
||||
extern {}
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
#[link(name = "System")]
|
||||
extern {}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user