Skip to content

Commit

Permalink
Implement flexible target specification
Browse files Browse the repository at this point in the history
Removes all target-specific knowledge from rustc. Some targets have changed
during this, but none of these should be very visible outside of
cross-compilation. The changes make our targets more consistent.

iX86-unknown-linux-gnu is now only available as i686-unknown-linux-gnu. We
used to accept any value of X greater than 1. i686 was released in 1995, and
should encompass the bare minimum of what Rust supports on x86 CPUs.

The only two windows targets are now i686-pc-windows-gnu and
x86_64-pc-windows-gnu.

The iOS target has been renamed from arm-apple-ios to arm-apple-darwin.

A complete list of the targets we accept now:

arm-apple-darwin
arm-linux-androideabi
arm-unknown-linux-gnueabi
arm-unknown-linux-gnueabihf

i686-apple-darwin
i686-pc-windows-gnu
i686-unknown-freebsd
i686-unknown-linux-gnu

mips-unknown-linux-gnu
mipsel-unknown-linux-gnu

x86_64-apple-darwin
x86_64-unknown-freebsd
x86_64-unknown-linux-gnu
x86_64-pc-windows-gnu

Closes rust-lang#16093

[breaking-change]
  • Loading branch information
emberian authored and eddyb committed Sep 20, 2014
1 parent 5d335c9 commit cc34113
Show file tree
Hide file tree
Showing 52 changed files with 1,539 additions and 840 deletions.
11 changes: 5 additions & 6 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -306,37 +306,36 @@ case $CFG_OSTYPE in
# instead, msys defines $MSYSTEM which is MINGW32 on i686 and
# MINGW64 on x86_64.
CFG_CPUTYPE=i686
CFG_OSTYPE=w64-mingw32
CFG_OSTYPE=pc-windows-gnu
if [ "$MSYSTEM" = MINGW64 ]
then
CFG_CPUTYPE=x86_64
CFG_OSTYPE=w64-mingw32
fi
;;

# Thad's Cygwin identifers below

# Vista 32 bit
CYGWIN_NT-6.0)
CFG_OSTYPE=pc-mingw32
CFG_OSTYPE=pc-windows-gnu
CFG_CPUTYPE=i686
;;

# Vista 64 bit
CYGWIN_NT-6.0-WOW64)
CFG_OSTYPE=w64-mingw32
CFG_OSTYPE=pc-windows-gnu
CFG_CPUTYPE=x86_64
;;

# Win 7 32 bit
CYGWIN_NT-6.1)
CFG_OSTYPE=pc-mingw32
CFG_OSTYPE=pc-windows-gnu
CFG_CPUTYPE=i686
;;

# Win 7 64 bit
CYGWIN_NT-6.1-WOW64)
CFG_OSTYPE=w64-mingw32
CFG_OSTYPE=pc-windows-gnu
CFG_CPUTYPE=x86_64
;;

Expand Down
331 changes: 151 additions & 180 deletions mk/platform.mk

Large diffs are not rendered by default.

271 changes: 88 additions & 183 deletions src/librustc/back/link.rs

Large diffs are not rendered by default.

59 changes: 27 additions & 32 deletions src/librustc/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use driver::config;
use llvm;
use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
use util::common::time;
use syntax::abi;
use syntax::codemap;
use syntax::diagnostic;
use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
Expand Down Expand Up @@ -151,20 +150,8 @@ impl Emitter for SharedEmitter {
// Note that without those flags various linking errors might
// arise as some of intrinsics 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 => {
if "" == sess.opts.cg.target_feature.as_slice() {
"+v7"
} 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()
}
fn target_feature(sess: &Session) -> String {
format!("{},{}", sess.target.target.options.features, sess.opts.cg.target_feature)
}

fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
Expand All @@ -177,7 +164,11 @@ fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
}

fn create_target_machine(sess: &Session) -> TargetMachineRef {
let reloc_model = match sess.opts.cg.relocation_model.as_slice() {
let reloc_model_arg = match sess.opts.cg.relocation_model {
Some(ref s) => s.as_slice(),
None => sess.target.target.options.relocation_model.as_slice()
};
let reloc_model = match reloc_model_arg {
"pic" => llvm::RelocPIC,
"static" => llvm::RelocStatic,
"default" => llvm::RelocDefault,
Expand All @@ -196,18 +187,18 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
let use_softfp = sess.opts.cg.soft_float;

// FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter.
// FIXME: #11954: mac64 unwinding may not work with fp elim
let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) ||
(sess.targ_cfg.os == abi::OsMacos &&
sess.targ_cfg.arch == abi::X86_64);
!sess.target.target.options.eliminate_frame_pointer;

// OSX has -dead_strip, which doesn't rely on ffunction_sections
// FIXME(#13846) this should be enabled for windows
let ffunction_sections = sess.targ_cfg.os != abi::OsMacos &&
sess.targ_cfg.os != abi::OsWindows;
let ffunction_sections = sess.target.target.options.function_sections;
let fdata_sections = ffunction_sections;

let code_model = match sess.opts.cg.code_model.as_slice() {
let code_model_arg = match sess.opts.cg.code_model {
Some(ref s) => s.as_slice(),
None => sess.target.target.options.code_model.as_slice()
};

let code_model = match code_model_arg {
"default" => llvm::CodeModelDefault,
"small" => llvm::CodeModelSmall,
"kernel" => llvm::CodeModelKernel,
Expand All @@ -224,12 +215,14 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
};

unsafe {
sess.targ_cfg
.target_strs
.target_triple
.as_slice()
.with_c_str(|t| {
sess.opts.cg.target_cpu.as_slice().with_c_str(|cpu| {
sess.target.target
.llvm_target
.as_slice()
.with_c_str(|t| {
match sess.opts.cg.target_cpu {
Some(ref s) => s.as_slice(),
None => sess.target.target.options.cpu.as_slice()
}.with_c_str(|cpu| {
target_feature(sess).with_c_str(|features| {
llvm::LLVMRustCreateTargetMachine(
t, cpu, features,
Expand Down Expand Up @@ -654,7 +647,7 @@ pub fn run_passes(sess: &Session,
// the desired path. This will give the correct behavior whether or
// not GCC adds --force-exe-suffix.
let windows_output_path =
if sess.targ_cfg.os == abi::OsWindows {
if sess.target.target.options.is_like_windows {
Some(output_path.with_extension("o.exe"))
} else {
None
Expand All @@ -663,7 +656,7 @@ pub fn run_passes(sess: &Session,
let pname = get_cc_prog(sess);
let mut cmd = Command::new(pname.as_slice());

cmd.args(sess.targ_cfg.target_strs.cc_args.as_slice());
cmd.args(sess.target.target.options.pre_link_args.as_slice());
cmd.arg("-nostdlib");

for index in range(0, trans.modules.len()) {
Expand All @@ -674,6 +667,8 @@ pub fn run_passes(sess: &Session,
.arg("-o")
.arg(windows_output_path.as_ref().unwrap_or(output_path));

cmd.args(sess.target.target.options.post_link_args.as_slice());

if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 {
println!("{}", &cmd);
}
Expand Down
157 changes: 53 additions & 104 deletions src/librustc/driver/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,14 @@ use driver::session::Session;

use back;
use back::write;
use back::target_strs;
use back::{arm, x86, x86_64, mips, mipsel};
use rustc_back::target::Target;
use lint;

use syntax::abi;
use syntax::ast;
use syntax::ast::{IntTy, UintTy};
use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::diagnostic::{ColorConfig, Auto, Always, Never};
use syntax::diagnostic::{ColorConfig, Auto, Always, Never, SpanHandler};
use syntax::parse;
use syntax::parse::token::InternedString;

Expand All @@ -39,9 +37,7 @@ use std::fmt;
use llvm;

pub struct Config {
pub os: abi::Os,
pub arch: abi::Architecture,
pub target_strs: target_strs::t,
pub target: Target,
pub int_type: IntTy,
pub uint_type: UintTy,
}
Expand Down Expand Up @@ -291,6 +287,13 @@ macro_rules! cgoptions(
}
}

fn parse_opt_bool(slot: &mut Option<bool>, v: Option<&str>) -> bool {
match v {
Some(..) => false,
None => { *slot = Some(true); true }
}
}

fn parse_opt_string(slot: &mut Option<String>, v: Option<&str>) -> bool {
match v {
Some(s) => { *slot = Some(s.to_string()); true },
Expand Down Expand Up @@ -318,6 +321,18 @@ macro_rules! cgoptions(
}
}

fn parse_opt_list(slot: &mut Option<Vec<String>>, v: Option<&str>)
-> bool {
match v {
Some(s) => {
let v = s.words().map(|s| s.to_string()).collect();
*slot = Some(v);
true
},
None => false,
}
}

fn parse_uint(slot: &mut uint, v: Option<&str>) -> bool {
use std::from_str::FromStr;
match v.and_then(FromStr::from_str) {
Expand Down Expand Up @@ -351,9 +366,9 @@ cgoptions!(
"tool to assemble archives with"),
linker: Option<String> = (None, parse_opt_string,
"system linker to link outputs with"),
link_args: Vec<String> = (Vec::new(), parse_list,
link_args: Option<Vec<String>> = (None, parse_opt_list,
"extra arguments to pass to the linker (space separated)"),
target_cpu: String = ("generic".to_string(), parse_string,
target_cpu: Option<String> = (None, parse_opt_string,
"select target processor (llc -mcpu=help for details)"),
target_feature: String = ("".to_string(), parse_string,
"target specific attributes (llc -mattr=help for details)"),
Expand All @@ -377,11 +392,11 @@ cgoptions!(
"prefer dynamic linking to static linking"),
no_integrated_as: bool = (false, parse_bool,
"use an external assembler rather than LLVM's integrated one"),
no_redzone: bool = (false, parse_bool,
no_redzone: Option<bool> = (None, parse_opt_bool,
"disable the use of the redzone"),
relocation_model: String = ("pic".to_string(), parse_string,
relocation_model: Option<String> = (None, parse_opt_string,
"choose the relocation model to use (llc -relocation-model for details)"),
code_model: String = ("default".to_string(), parse_string,
code_model: Option<String> = (None, parse_opt_string,
"choose the code model to use (llc -code-model for details)"),
metadata: Vec<String> = (Vec::new(), parse_list,
"metadata to mangle symbol names with"),
Expand Down Expand Up @@ -433,40 +448,27 @@ pub fn default_lib_output() -> CrateType {
}

pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
let tos = match sess.targ_cfg.os {
abi::OsWindows => InternedString::new("windows"),
abi::OsMacos => InternedString::new("macos"),
abi::OsLinux => InternedString::new("linux"),
abi::OsAndroid => InternedString::new("android"),
abi::OsFreebsd => InternedString::new("freebsd"),
abi::OsDragonfly => InternedString::new("dragonfly"),
abi::OsiOS => InternedString::new("ios"),
};
use syntax::parse::token::intern_and_get_ident as intern;

// ARM is bi-endian, however using NDK seems to default
// to little-endian unless a flag is provided.
let (end,arch,wordsz) = match sess.targ_cfg.arch {
abi::X86 => ("little", "x86", "32"),
abi::X86_64 => ("little", "x86_64", "64"),
abi::Arm => ("little", "arm", "32"),
abi::Mips => ("big", "mips", "32"),
abi::Mipsel => ("little", "mipsel", "32")
};
let end = sess.target.target.target_endian.as_slice();
let arch = sess.target.target.arch.as_slice();
let wordsz = sess.target.target.target_word_size.as_slice();
let os = sess.target.target.target_os.as_slice();

let fam = match sess.targ_cfg.os {
abi::OsWindows => InternedString::new("windows"),
_ => InternedString::new("unix")
let fam = match sess.target.target.options.is_like_windows {
true => InternedString::new("windows"),
false => InternedString::new("unix")
};

let mk = attr::mk_name_value_item_str;
return vec!(// Target bindings.
attr::mk_word_item(fam.clone()),
mk(InternedString::new("target_os"), tos),
mk(InternedString::new("target_os"), intern(os)),
mk(InternedString::new("target_family"), fam),
mk(InternedString::new("target_arch"), InternedString::new(arch)),
mk(InternedString::new("target_endian"), InternedString::new(end)),
mk(InternedString::new("target_arch"), intern(arch)),
mk(InternedString::new("target_endian"), intern(end)),
mk(InternedString::new("target_word_size"),
InternedString::new(wordsz))
intern(wordsz))
);
}

Expand All @@ -489,76 +491,23 @@ pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
user_cfg.into_iter().collect::<Vec<_>>().append(default_cfg.as_slice())
}

pub fn get_os(triple: &str) -> Option<abi::Os> {
for &(name, os) in os_names.iter() {
if triple.contains(name) { return Some(os) }
}
None
}
static os_names : &'static [(&'static str, abi::Os)] = &[
("mingw32", abi::OsWindows),
("win32", abi::OsWindows),
("windows", abi::OsWindows),
("darwin", abi::OsMacos),
("android", abi::OsAndroid),
("linux", abi::OsLinux),
("freebsd", abi::OsFreebsd),
("dragonfly", abi::OsDragonfly),
("ios", abi::OsiOS)];

pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
for &(arch, abi) in architecture_abis.iter() {
if triple.contains(arch) { return Some(abi) }
}
None
}
static architecture_abis : &'static [(&'static str, abi::Architecture)] = &[
("i386", abi::X86),
("i486", abi::X86),
("i586", abi::X86),
("i686", abi::X86),
("i786", abi::X86),

("x86_64", abi::X86_64),

("arm", abi::Arm),
("xscale", abi::Arm),
("thumb", abi::Arm),

("mipsel", abi::Mipsel),
("mips", abi::Mips)];

pub fn build_target_config(sopts: &Options) -> Config {
let os = match get_os(sopts.target_triple.as_slice()) {
Some(os) => os,
None => early_error("unknown operating system")
};
let arch = match get_arch(sopts.target_triple.as_slice()) {
Some(arch) => arch,
None => {
early_error(format!("unknown architecture: {}",
sopts.target_triple.as_slice()).as_slice())
}
};
let (int_type, uint_type) = match arch {
abi::X86 => (ast::TyI32, ast::TyU32),
abi::X86_64 => (ast::TyI64, ast::TyU64),
abi::Arm => (ast::TyI32, ast::TyU32),
abi::Mips => (ast::TyI32, ast::TyU32),
abi::Mipsel => (ast::TyI32, ast::TyU32)
pub fn build_target_config(opts: &Options, sp: &SpanHandler) -> Config {
let target = match Target::search(opts.target_triple.as_slice()) {
Ok(t) => t,
Err(e) => {
sp.handler().fatal((format!("Error loading target specification: {}", e)).as_slice());
}
};
let target_triple = sopts.target_triple.clone();
let target_strs = match arch {
abi::X86 => x86::get_target_strs(target_triple, os),
abi::X86_64 => x86_64::get_target_strs(target_triple, os),
abi::Arm => arm::get_target_strs(target_triple, os),
abi::Mips => mips::get_target_strs(target_triple, os),
abi::Mipsel => mipsel::get_target_strs(target_triple, os)

let (int_type, uint_type) = match target.target_word_size.as_slice() {
"32" => (ast::TyI32, ast::TyU32),
"64" => (ast::TyI64, ast::TyU64),
w => sp.handler().fatal((format!("target specification was invalid: unrecognized \
target-word-size {}", w)).as_slice())
};

Config {
os: os,
arch: arch,
target_strs: target_strs,
target: target,
int_type: int_type,
uint_type: uint_type,
}
Expand Down
Loading

0 comments on commit cc34113

Please sign in to comment.