Basic iOS support

This commit is contained in:
Valerii Hiora 2014-05-05 10:07:49 +03:00
parent 0c10c68682
commit a49b765f9a
37 changed files with 461 additions and 65 deletions

View file

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

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

View file

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

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

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

View file

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

View file

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

View file

@ -249,4 +249,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")) {

View file

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

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

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