auto merge of #14096 : nick29581/rust/driver, r=brson
The goal of this refactoring is to make the rustc driver code easier to understand and use. Since this is as close to an API as we have, I think it is important that it is nice. On getting stuck in, I found that there wasn't as much to change as I'd hoped to make the stage... functions easier to use by tools (which is a good thing :-) ). This patch only moves code around - mostly just moving code to different files, but a few extracted method refactorings too. To summarise the changes: I added driver::config which handles everything about configuring the compiler. driver::session now just defines and builds session objects. I moved driver code from librustc/lib.rs to librustc/driver/mod.rs so all the code is one place. I extracted methods to make emulating the compiler without being the compiler a little easier. Within the driver directory, I moved code around to more logically fit in the modules.
This commit is contained in:
commit
e031ba1028
27 changed files with 1447 additions and 1377 deletions
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use back::target_strs;
|
use back::target_strs;
|
||||||
use driver::session::sess_os_to_meta_os;
|
use driver::config::cfg_os_to_meta_os;
|
||||||
use metadata::loader::meta_section_name;
|
use metadata::loader::meta_section_name;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::
|
||||||
return target_strs::t {
|
return target_strs::t {
|
||||||
module_asm: "".to_owned(),
|
module_asm: "".to_owned(),
|
||||||
|
|
||||||
meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
|
meta_sect_name: meta_section_name(cfg_os_to_meta_os(target_os)).to_owned(),
|
||||||
|
|
||||||
data_layout: match target_os {
|
data_layout: match target_os {
|
||||||
abi::OsMacos => {
|
abi::OsMacos => {
|
||||||
|
|
|
@ -12,8 +12,9 @@ use back::archive::{Archive, METADATA_FILENAME};
|
||||||
use back::rpath;
|
use back::rpath;
|
||||||
use back::svh::Svh;
|
use back::svh::Svh;
|
||||||
use driver::driver::{CrateTranslation, OutputFilenames};
|
use driver::driver::{CrateTranslation, OutputFilenames};
|
||||||
use driver::session::{NoDebugInfo, Session};
|
use driver::config::NoDebugInfo;
|
||||||
use driver::session;
|
use driver::session::Session;
|
||||||
|
use driver::config;
|
||||||
use lib::llvm::llvm;
|
use lib::llvm::llvm;
|
||||||
use lib::llvm::ModuleRef;
|
use lib::llvm::ModuleRef;
|
||||||
use lib;
|
use lib;
|
||||||
|
@ -92,8 +93,9 @@ pub mod write {
|
||||||
use back::link::{OutputTypeExe, OutputTypeLlvmAssembly};
|
use back::link::{OutputTypeExe, OutputTypeLlvmAssembly};
|
||||||
use back::link::{OutputTypeObject};
|
use back::link::{OutputTypeObject};
|
||||||
use driver::driver::{CrateTranslation, OutputFilenames};
|
use driver::driver::{CrateTranslation, OutputFilenames};
|
||||||
use driver::session::{NoDebugInfo, Session};
|
use driver::config::NoDebugInfo;
|
||||||
use driver::session;
|
use driver::session::Session;
|
||||||
|
use driver::config;
|
||||||
use lib::llvm::llvm;
|
use lib::llvm::llvm;
|
||||||
use lib::llvm::{ModuleRef, TargetMachineRef, PassManagerRef};
|
use lib::llvm::{ModuleRef, TargetMachineRef, PassManagerRef};
|
||||||
use lib;
|
use lib;
|
||||||
|
@ -139,10 +141,10 @@ pub mod write {
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt_level = match sess.opts.optimize {
|
let opt_level = match sess.opts.optimize {
|
||||||
session::No => lib::llvm::CodeGenLevelNone,
|
config::No => lib::llvm::CodeGenLevelNone,
|
||||||
session::Less => lib::llvm::CodeGenLevelLess,
|
config::Less => lib::llvm::CodeGenLevelLess,
|
||||||
session::Default => lib::llvm::CodeGenLevelDefault,
|
config::Default => lib::llvm::CodeGenLevelDefault,
|
||||||
session::Aggressive => lib::llvm::CodeGenLevelAggressive,
|
config::Aggressive => lib::llvm::CodeGenLevelAggressive,
|
||||||
};
|
};
|
||||||
let use_softfp = sess.opts.cg.soft_float;
|
let use_softfp = sess.opts.cg.soft_float;
|
||||||
|
|
||||||
|
@ -231,7 +233,7 @@ pub mod write {
|
||||||
// emitting an rlib. Whenever an rlib is created, the bytecode is
|
// emitting an rlib. Whenever an rlib is created, the bytecode is
|
||||||
// inserted into the archive in order to allow LTO against it.
|
// inserted into the archive in order to allow LTO against it.
|
||||||
if sess.opts.cg.save_temps ||
|
if sess.opts.cg.save_temps ||
|
||||||
(sess.crate_types.borrow().contains(&session::CrateTypeRlib) &&
|
(sess.crate_types.borrow().contains(&config::CrateTypeRlib) &&
|
||||||
sess.opts.output_types.contains(&OutputTypeExe)) {
|
sess.opts.output_types.contains(&OutputTypeExe)) {
|
||||||
output.temp_path(OutputTypeBitcode).with_c_str(|buf| {
|
output.temp_path(OutputTypeBitcode).with_c_str(|buf| {
|
||||||
llvm::LLVMWriteBitcodeToFile(llmod, buf);
|
llvm::LLVMWriteBitcodeToFile(llmod, buf);
|
||||||
|
@ -378,10 +380,10 @@ pub mod write {
|
||||||
// Copy what clang does by turning on loop vectorization at O2 and
|
// Copy what clang does by turning on loop vectorization at O2 and
|
||||||
// slp vectorization at O3
|
// slp vectorization at O3
|
||||||
let vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
|
let vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
|
||||||
(sess.opts.optimize == session::Default ||
|
(sess.opts.optimize == config::Default ||
|
||||||
sess.opts.optimize == session::Aggressive);
|
sess.opts.optimize == config::Aggressive);
|
||||||
let vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
|
let vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
|
||||||
sess.opts.optimize == session::Aggressive;
|
sess.opts.optimize == config::Aggressive;
|
||||||
|
|
||||||
let mut llvm_c_strs = Vec::new();
|
let mut llvm_c_strs = Vec::new();
|
||||||
let mut llvm_args = Vec::new();
|
let mut llvm_args = Vec::new();
|
||||||
|
@ -823,14 +825,14 @@ fn is_writeable(p: &Path) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filename_for_input(sess: &Session, crate_type: session::CrateType,
|
pub fn filename_for_input(sess: &Session, crate_type: config::CrateType,
|
||||||
id: &CrateId, out_filename: &Path) -> Path {
|
id: &CrateId, out_filename: &Path) -> Path {
|
||||||
let libname = output_lib_filename(id);
|
let libname = output_lib_filename(id);
|
||||||
match crate_type {
|
match crate_type {
|
||||||
session::CrateTypeRlib => {
|
config::CrateTypeRlib => {
|
||||||
out_filename.with_filename(format!("lib{}.rlib", libname))
|
out_filename.with_filename(format!("lib{}.rlib", libname))
|
||||||
}
|
}
|
||||||
session::CrateTypeDylib => {
|
config::CrateTypeDylib => {
|
||||||
let (prefix, suffix) = match sess.targ_cfg.os {
|
let (prefix, suffix) = match sess.targ_cfg.os {
|
||||||
abi::OsWin32 => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX),
|
abi::OsWin32 => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX),
|
||||||
abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX),
|
abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX),
|
||||||
|
@ -840,16 +842,16 @@ pub fn filename_for_input(sess: &Session, crate_type: session::CrateType,
|
||||||
};
|
};
|
||||||
out_filename.with_filename(format!("{}{}{}", prefix, libname, suffix))
|
out_filename.with_filename(format!("{}{}{}", prefix, libname, suffix))
|
||||||
}
|
}
|
||||||
session::CrateTypeStaticlib => {
|
config::CrateTypeStaticlib => {
|
||||||
out_filename.with_filename(format!("lib{}.a", libname))
|
out_filename.with_filename(format!("lib{}.a", libname))
|
||||||
}
|
}
|
||||||
session::CrateTypeExecutable => out_filename.clone(),
|
config::CrateTypeExecutable => out_filename.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn link_binary_output(sess: &Session,
|
fn link_binary_output(sess: &Session,
|
||||||
trans: &CrateTranslation,
|
trans: &CrateTranslation,
|
||||||
crate_type: session::CrateType,
|
crate_type: config::CrateType,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
id: &CrateId) -> Path {
|
id: &CrateId) -> Path {
|
||||||
let obj_filename = outputs.temp_path(OutputTypeObject);
|
let obj_filename = outputs.temp_path(OutputTypeObject);
|
||||||
|
@ -877,16 +879,16 @@ fn link_binary_output(sess: &Session,
|
||||||
}
|
}
|
||||||
|
|
||||||
match crate_type {
|
match crate_type {
|
||||||
session::CrateTypeRlib => {
|
config::CrateTypeRlib => {
|
||||||
link_rlib(sess, Some(trans), &obj_filename, &out_filename);
|
link_rlib(sess, Some(trans), &obj_filename, &out_filename);
|
||||||
}
|
}
|
||||||
session::CrateTypeStaticlib => {
|
config::CrateTypeStaticlib => {
|
||||||
link_staticlib(sess, &obj_filename, &out_filename);
|
link_staticlib(sess, &obj_filename, &out_filename);
|
||||||
}
|
}
|
||||||
session::CrateTypeExecutable => {
|
config::CrateTypeExecutable => {
|
||||||
link_natively(sess, trans, false, &obj_filename, &out_filename);
|
link_natively(sess, trans, false, &obj_filename, &out_filename);
|
||||||
}
|
}
|
||||||
session::CrateTypeDylib => {
|
config::CrateTypeDylib => {
|
||||||
link_natively(sess, trans, true, &obj_filename, &out_filename);
|
link_natively(sess, trans, true, &obj_filename, &out_filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1045,7 +1047,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
|
||||||
let mut cc_args = sess.targ_cfg.target_strs.cc_args.clone();
|
let mut cc_args = sess.targ_cfg.target_strs.cc_args.clone();
|
||||||
cc_args.push_all_move(link_args(sess, dylib, tmpdir.path(), trans,
|
cc_args.push_all_move(link_args(sess, dylib, tmpdir.path(), trans,
|
||||||
obj_filename, out_filename));
|
obj_filename, out_filename));
|
||||||
if (sess.opts.debugging_opts & session::PRINT_LINK_ARGS) != 0 {
|
if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 {
|
||||||
println!("{} link args: '{}'", cc_prog, cc_args.connect("' '"));
|
println!("{} link args: '{}'", cc_prog, cc_args.connect("' '"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1161,8 +1163,8 @@ fn link_args(sess: &Session,
|
||||||
|
|
||||||
// GNU-style linkers support optimization with -O. GNU ld doesn't need a
|
// GNU-style linkers support optimization with -O. GNU ld doesn't need a
|
||||||
// numeric argument, but other linkers do.
|
// numeric argument, but other linkers do.
|
||||||
if sess.opts.optimize == session::Default ||
|
if sess.opts.optimize == config::Default ||
|
||||||
sess.opts.optimize == session::Aggressive {
|
sess.opts.optimize == config::Aggressive {
|
||||||
args.push("-Wl,-O1".to_owned());
|
args.push("-Wl,-O1".to_owned());
|
||||||
}
|
}
|
||||||
} else if sess.targ_cfg.os == abi::OsMacos {
|
} else if sess.targ_cfg.os == abi::OsMacos {
|
||||||
|
@ -1373,9 +1375,9 @@ fn add_upstream_rust_crates(args: &mut Vec<~str>, sess: &Session,
|
||||||
// involves just passing the right -l flag.
|
// involves just passing the right -l flag.
|
||||||
|
|
||||||
let data = if dylib {
|
let data = if dylib {
|
||||||
trans.crate_formats.get(&session::CrateTypeDylib)
|
trans.crate_formats.get(&config::CrateTypeDylib)
|
||||||
} else {
|
} else {
|
||||||
trans.crate_formats.get(&session::CrateTypeExecutable)
|
trans.crate_formats.get(&config::CrateTypeExecutable)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Invoke get_used_crates to ensure that we get a topological sorting of
|
// Invoke get_used_crates to ensure that we get a topological sorting of
|
||||||
|
@ -1403,7 +1405,7 @@ fn add_upstream_rust_crates(args: &mut Vec<~str>, sess: &Session,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts a library file-stem into a cc -l argument
|
// Converts a library file-stem into a cc -l argument
|
||||||
fn unlib(config: &session::Config, stem: &str) -> ~str {
|
fn unlib(config: &config::Config, stem: &str) -> ~str {
|
||||||
if stem.starts_with("lib") && config.os != abi::OsWin32 {
|
if stem.starts_with("lib") && config.os != abi::OsWin32 {
|
||||||
stem.slice(3, stem.len()).to_owned()
|
stem.slice(3, stem.len()).to_owned()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
use back::archive::ArchiveRO;
|
use back::archive::ArchiveRO;
|
||||||
use back::link;
|
use back::link;
|
||||||
use driver::session;
|
use driver::session;
|
||||||
|
use driver::config;
|
||||||
use lib::llvm::{ModuleRef, TargetMachineRef, llvm, True, False};
|
use lib::llvm::{ModuleRef, TargetMachineRef, llvm, True, False};
|
||||||
use metadata::cstore;
|
use metadata::cstore;
|
||||||
use util::common::time;
|
use util::common::time;
|
||||||
|
@ -29,7 +30,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
|
||||||
// Make sure we actually can run LTO
|
// Make sure we actually can run LTO
|
||||||
for crate_type in sess.crate_types.borrow().iter() {
|
for crate_type in sess.crate_types.borrow().iter() {
|
||||||
match *crate_type {
|
match *crate_type {
|
||||||
session::CrateTypeExecutable | session::CrateTypeStaticlib => {}
|
config::CrateTypeExecutable | config::CrateTypeStaticlib => {}
|
||||||
_ => {
|
_ => {
|
||||||
sess.fatal("lto can only be run for executables and \
|
sess.fatal("lto can only be run for executables and \
|
||||||
static library outputs");
|
static library outputs");
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use back::target_strs;
|
use back::target_strs;
|
||||||
use driver::session::sess_os_to_meta_os;
|
use driver::config::cfg_os_to_meta_os;
|
||||||
use metadata::loader::meta_section_name;
|
use metadata::loader::meta_section_name;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::
|
||||||
return target_strs::t {
|
return target_strs::t {
|
||||||
module_asm: "".to_owned(),
|
module_asm: "".to_owned(),
|
||||||
|
|
||||||
meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
|
meta_sect_name: meta_section_name(cfg_os_to_meta_os(target_os)).to_owned(),
|
||||||
|
|
||||||
data_layout: match target_os {
|
data_layout: match target_os {
|
||||||
abi::OsMacos => {
|
abi::OsMacos => {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
|
|
||||||
use back::target_strs;
|
use back::target_strs;
|
||||||
use driver::session::sess_os_to_meta_os;
|
use driver::config::cfg_os_to_meta_os;
|
||||||
use metadata::loader::meta_section_name;
|
use metadata::loader::meta_section_name;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::
|
||||||
return target_strs::t {
|
return target_strs::t {
|
||||||
module_asm: "".to_owned(),
|
module_asm: "".to_owned(),
|
||||||
|
|
||||||
meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
|
meta_sect_name: meta_section_name(cfg_os_to_meta_os(target_os)).to_owned(),
|
||||||
|
|
||||||
data_layout: match target_os {
|
data_layout: match target_os {
|
||||||
abi::OsMacos => {
|
abi::OsMacos => {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
|
|
||||||
use back::target_strs;
|
use back::target_strs;
|
||||||
use driver::session::sess_os_to_meta_os;
|
use driver::config::cfg_os_to_meta_os;
|
||||||
use metadata::loader::meta_section_name;
|
use metadata::loader::meta_section_name;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::
|
||||||
return target_strs::t {
|
return target_strs::t {
|
||||||
module_asm: "".to_owned(),
|
module_asm: "".to_owned(),
|
||||||
|
|
||||||
meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
|
meta_sect_name: meta_section_name(cfg_os_to_meta_os(target_os)).to_owned(),
|
||||||
|
|
||||||
data_layout: match target_os {
|
data_layout: match target_os {
|
||||||
abi::OsMacos => {
|
abi::OsMacos => {
|
||||||
|
|
769
src/librustc/driver/config.rs
Normal file
769
src/librustc/driver/config.rs
Normal file
|
@ -0,0 +1,769 @@
|
||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! Contains infrastructure for configuring the compiler, including parsing
|
||||||
|
//! command line options.
|
||||||
|
|
||||||
|
use driver::early_error;
|
||||||
|
use driver::driver;
|
||||||
|
use driver::session::Session;
|
||||||
|
|
||||||
|
use back;
|
||||||
|
use back::link;
|
||||||
|
use back::target_strs;
|
||||||
|
use back::{arm, x86, x86_64, mips};
|
||||||
|
use metadata;
|
||||||
|
use middle::lint;
|
||||||
|
|
||||||
|
use syntax::abi;
|
||||||
|
use syntax::ast;
|
||||||
|
use syntax::ast::{IntTy, UintTy};
|
||||||
|
use syntax::attr;
|
||||||
|
use syntax::attr::AttrMetaMethods;
|
||||||
|
use syntax::parse;
|
||||||
|
use syntax::parse::token::InternedString;
|
||||||
|
|
||||||
|
use collections::HashSet;
|
||||||
|
use getopts::{optopt, optmulti, optflag, optflagopt};
|
||||||
|
use getopts;
|
||||||
|
use lib::llvm::llvm;
|
||||||
|
use std::cell::{RefCell};
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Config {
|
||||||
|
pub os: abi::Os,
|
||||||
|
pub arch: abi::Architecture,
|
||||||
|
pub target_strs: target_strs::t,
|
||||||
|
pub int_type: IntTy,
|
||||||
|
pub uint_type: UintTy,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone, Eq)]
|
||||||
|
pub enum OptLevel {
|
||||||
|
No, // -O0
|
||||||
|
Less, // -O1
|
||||||
|
Default, // -O2
|
||||||
|
Aggressive // -O3
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone, Eq)]
|
||||||
|
pub enum DebugInfoLevel {
|
||||||
|
NoDebugInfo,
|
||||||
|
LimitedDebugInfo,
|
||||||
|
FullDebugInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
|
pub struct Options {
|
||||||
|
// The crate config requested for the session, which may be combined
|
||||||
|
// with additional crate configurations during the compile process
|
||||||
|
pub crate_types: Vec<CrateType>,
|
||||||
|
|
||||||
|
pub gc: bool,
|
||||||
|
pub optimize: OptLevel,
|
||||||
|
pub debuginfo: DebugInfoLevel,
|
||||||
|
pub lint_opts: Vec<(lint::Lint, lint::level)> ,
|
||||||
|
pub output_types: Vec<back::link::OutputType> ,
|
||||||
|
// This was mutable for rustpkg, which updates search paths based on the
|
||||||
|
// parsed code. It remains mutable in case its replacements wants to use
|
||||||
|
// this.
|
||||||
|
pub addl_lib_search_paths: RefCell<HashSet<Path>>,
|
||||||
|
pub maybe_sysroot: Option<Path>,
|
||||||
|
pub target_triple: ~str,
|
||||||
|
// User-specified cfg meta items. The compiler itself will add additional
|
||||||
|
// items to the crate config, and during parsing the entire crate config
|
||||||
|
// will be added to the crate AST node. This should not be used for
|
||||||
|
// anything except building the full crate config prior to parsing.
|
||||||
|
pub cfg: ast::CrateConfig,
|
||||||
|
pub test: bool,
|
||||||
|
pub parse_only: bool,
|
||||||
|
pub no_trans: bool,
|
||||||
|
pub no_analysis: bool,
|
||||||
|
pub debugging_opts: u64,
|
||||||
|
/// Whether to write dependency files. It's (enabled, optional filename).
|
||||||
|
pub write_dependency_info: (bool, Option<Path>),
|
||||||
|
/// Crate id-related things to maybe print. It's (crate_id, crate_name, crate_file_name).
|
||||||
|
pub print_metas: (bool, bool, bool),
|
||||||
|
pub cg: CodegenOptions,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Some reasonable defaults
|
||||||
|
pub fn basic_options() -> Options {
|
||||||
|
Options {
|
||||||
|
crate_types: Vec::new(),
|
||||||
|
gc: false,
|
||||||
|
optimize: No,
|
||||||
|
debuginfo: NoDebugInfo,
|
||||||
|
lint_opts: Vec::new(),
|
||||||
|
output_types: Vec::new(),
|
||||||
|
addl_lib_search_paths: RefCell::new(HashSet::new()),
|
||||||
|
maybe_sysroot: None,
|
||||||
|
target_triple: driver::host_triple().to_owned(),
|
||||||
|
cfg: Vec::new(),
|
||||||
|
test: false,
|
||||||
|
parse_only: false,
|
||||||
|
no_trans: false,
|
||||||
|
no_analysis: false,
|
||||||
|
debugging_opts: 0,
|
||||||
|
write_dependency_info: (false, None),
|
||||||
|
print_metas: (false, false, false),
|
||||||
|
cg: basic_codegen_options(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The type of entry function, so
|
||||||
|
// users can have their own entry
|
||||||
|
// functions that don't start a
|
||||||
|
// scheduler
|
||||||
|
#[deriving(Eq)]
|
||||||
|
pub enum EntryFnType {
|
||||||
|
EntryMain,
|
||||||
|
EntryStart,
|
||||||
|
EntryNone,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deriving(Eq, Ord, Clone, TotalOrd, TotalEq, Hash)]
|
||||||
|
pub enum CrateType {
|
||||||
|
CrateTypeExecutable,
|
||||||
|
CrateTypeDylib,
|
||||||
|
CrateTypeRlib,
|
||||||
|
CrateTypeStaticlib,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! debugging_opts(
|
||||||
|
([ $opt:ident ] $cnt:expr ) => (
|
||||||
|
pub static $opt: u64 = 1 << $cnt;
|
||||||
|
);
|
||||||
|
([ $opt:ident, $($rest:ident),* ] $cnt:expr ) => (
|
||||||
|
pub static $opt: u64 = 1 << $cnt;
|
||||||
|
debugging_opts!([ $($rest),* ] $cnt + 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
debugging_opts!(
|
||||||
|
[
|
||||||
|
VERBOSE,
|
||||||
|
TIME_PASSES,
|
||||||
|
COUNT_LLVM_INSNS,
|
||||||
|
TIME_LLVM_PASSES,
|
||||||
|
TRANS_STATS,
|
||||||
|
ASM_COMMENTS,
|
||||||
|
NO_VERIFY,
|
||||||
|
BORROWCK_STATS,
|
||||||
|
NO_LANDING_PADS,
|
||||||
|
DEBUG_LLVM,
|
||||||
|
SHOW_SPAN,
|
||||||
|
COUNT_TYPE_SIZES,
|
||||||
|
META_STATS,
|
||||||
|
NO_OPT,
|
||||||
|
GC,
|
||||||
|
PRINT_LINK_ARGS,
|
||||||
|
PRINT_LLVM_PASSES,
|
||||||
|
LTO,
|
||||||
|
AST_JSON,
|
||||||
|
AST_JSON_NOEXPAND,
|
||||||
|
LS
|
||||||
|
]
|
||||||
|
0
|
||||||
|
)
|
||||||
|
|
||||||
|
pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
|
||||||
|
vec!(("verbose", "in general, enable more debug printouts", VERBOSE),
|
||||||
|
("time-passes", "measure time of each rustc pass", TIME_PASSES),
|
||||||
|
("count-llvm-insns", "count where LLVM \
|
||||||
|
instrs originate", COUNT_LLVM_INSNS),
|
||||||
|
("time-llvm-passes", "measure time of each LLVM pass",
|
||||||
|
TIME_LLVM_PASSES),
|
||||||
|
("trans-stats", "gather trans statistics", TRANS_STATS),
|
||||||
|
("asm-comments", "generate comments into the assembly (may change behavior)",
|
||||||
|
ASM_COMMENTS),
|
||||||
|
("no-verify", "skip LLVM verification", NO_VERIFY),
|
||||||
|
("borrowck-stats", "gather borrowck statistics", BORROWCK_STATS),
|
||||||
|
("no-landing-pads", "omit landing pads for unwinding",
|
||||||
|
NO_LANDING_PADS),
|
||||||
|
("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM),
|
||||||
|
("show-span", "show spans for compiler debugging", SHOW_SPAN),
|
||||||
|
("count-type-sizes", "count the sizes of aggregate types",
|
||||||
|
COUNT_TYPE_SIZES),
|
||||||
|
("meta-stats", "gather metadata statistics", META_STATS),
|
||||||
|
("no-opt", "do not optimize, even if -O is passed", NO_OPT),
|
||||||
|
("print-link-args", "Print the arguments passed to the linker",
|
||||||
|
PRINT_LINK_ARGS),
|
||||||
|
("gc", "Garbage collect shared data (experimental)", GC),
|
||||||
|
("print-llvm-passes",
|
||||||
|
"Prints the llvm optimization passes being run",
|
||||||
|
PRINT_LLVM_PASSES),
|
||||||
|
("lto", "Perform LLVM link-time optimizations", LTO),
|
||||||
|
("ast-json", "Print the AST as JSON and halt", AST_JSON),
|
||||||
|
("ast-json-noexpand", "Print the pre-expansion AST as JSON and halt", AST_JSON_NOEXPAND),
|
||||||
|
("ls", "List the symbols defined by a library crate", LS))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Declare a macro that will define all CodegenOptions fields and parsers all
|
||||||
|
/// at once. The goal of this macro is to define an interface that can be
|
||||||
|
/// programmatically used by the option parser in order to initialize the struct
|
||||||
|
/// without hardcoding field names all over the place.
|
||||||
|
///
|
||||||
|
/// The goal is to invoke this macro once with the correct fields, and then this
|
||||||
|
/// macro generates all necessary code. The main gotcha of this macro is the
|
||||||
|
/// cgsetters module which is a bunch of generated code to parse an option into
|
||||||
|
/// its respective field in the struct. There are a few hand-written parsers for
|
||||||
|
/// parsing specific types of values in this module.
|
||||||
|
macro_rules! cgoptions(
|
||||||
|
($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
|
||||||
|
(
|
||||||
|
#[deriving(Clone)]
|
||||||
|
pub struct CodegenOptions { $(pub $opt: $t),* }
|
||||||
|
|
||||||
|
pub fn basic_codegen_options() -> CodegenOptions {
|
||||||
|
CodegenOptions { $($opt: $init),* }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool;
|
||||||
|
pub static CG_OPTIONS: &'static [(&'static str, CodegenSetter,
|
||||||
|
&'static str)] =
|
||||||
|
&[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ];
|
||||||
|
|
||||||
|
mod cgsetters {
|
||||||
|
use super::CodegenOptions;
|
||||||
|
|
||||||
|
$(
|
||||||
|
pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool {
|
||||||
|
$parse(&mut cg.$opt, v)
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
|
fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
|
||||||
|
match v {
|
||||||
|
Some(..) => false,
|
||||||
|
None => { *slot = true; true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_opt_string(slot: &mut Option<~str>, v: Option<&str>) -> bool {
|
||||||
|
match v {
|
||||||
|
Some(s) => { *slot = Some(s.to_owned()); true },
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_string(slot: &mut ~str, v: Option<&str>) -> bool {
|
||||||
|
match v {
|
||||||
|
Some(s) => { *slot = s.to_owned(); true },
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_list(slot: &mut Vec<~str>, v: Option<&str>)
|
||||||
|
-> bool {
|
||||||
|
match v {
|
||||||
|
Some(s) => {
|
||||||
|
for s in s.words() {
|
||||||
|
slot.push(s.to_owned());
|
||||||
|
}
|
||||||
|
true
|
||||||
|
},
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
) )
|
||||||
|
|
||||||
|
cgoptions!(
|
||||||
|
ar: Option<~str> = (None, parse_opt_string,
|
||||||
|
"tool to assemble archives with"),
|
||||||
|
linker: Option<~str> = (None, parse_opt_string,
|
||||||
|
"system linker to link outputs with"),
|
||||||
|
link_args: Vec<~str> = (Vec::new(), parse_list,
|
||||||
|
"extra arguments to pass to the linker (space separated)"),
|
||||||
|
target_cpu: ~str = ("generic".to_owned(), parse_string,
|
||||||
|
"select target processor (llc -mcpu=help for details)"),
|
||||||
|
target_feature: ~str = ("".to_owned(), parse_string,
|
||||||
|
"target specific attributes (llc -mattr=help for details)"),
|
||||||
|
passes: Vec<~str> = (Vec::new(), parse_list,
|
||||||
|
"a list of extra LLVM passes to run (space separated)"),
|
||||||
|
llvm_args: Vec<~str> = (Vec::new(), parse_list,
|
||||||
|
"a list of arguments to pass to llvm (space separated)"),
|
||||||
|
save_temps: bool = (false, parse_bool,
|
||||||
|
"save all temporary output files during compilation"),
|
||||||
|
android_cross_path: Option<~str> = (None, parse_opt_string,
|
||||||
|
"the path to the Android NDK"),
|
||||||
|
no_rpath: bool = (false, parse_bool,
|
||||||
|
"disables setting the rpath in libs/exes"),
|
||||||
|
no_prepopulate_passes: bool = (false, parse_bool,
|
||||||
|
"don't pre-populate the pass manager with a list of passes"),
|
||||||
|
no_vectorize_loops: bool = (false, parse_bool,
|
||||||
|
"don't run the loop vectorization optimization passes"),
|
||||||
|
no_vectorize_slp: bool = (false, parse_bool,
|
||||||
|
"don't run LLVM's SLP vectorization pass"),
|
||||||
|
soft_float: bool = (false, parse_bool,
|
||||||
|
"generate software floating point library calls"),
|
||||||
|
prefer_dynamic: bool = (false, parse_bool,
|
||||||
|
"prefer dynamic linking to static linking"),
|
||||||
|
no_integrated_as: bool = (false, parse_bool,
|
||||||
|
"use an external assembler rather than LLVM's integrated one"),
|
||||||
|
relocation_model: ~str = ("pic".to_owned(), parse_string,
|
||||||
|
"choose the relocation model to use (llc -relocation-model for details)"),
|
||||||
|
)
|
||||||
|
|
||||||
|
pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
|
||||||
|
{
|
||||||
|
let mut cg = basic_codegen_options();
|
||||||
|
for option in matches.opt_strs("C").move_iter() {
|
||||||
|
let mut iter = option.splitn('=', 1);
|
||||||
|
let key = iter.next().unwrap();
|
||||||
|
let value = iter.next();
|
||||||
|
let option_to_lookup = key.replace("-", "_");
|
||||||
|
let mut found = false;
|
||||||
|
for &(candidate, setter, _) in CG_OPTIONS.iter() {
|
||||||
|
if option_to_lookup.as_slice() != candidate { continue }
|
||||||
|
if !setter(&mut cg, value) {
|
||||||
|
match value {
|
||||||
|
Some(..) => early_error(format!("codegen option `{}` takes \
|
||||||
|
no value", key)),
|
||||||
|
None => early_error(format!("codegen option `{0}` requires \
|
||||||
|
a value (-C {0}=<value>)",
|
||||||
|
key))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
early_error(format!("unknown codegen option: `{}`", key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cg;
|
||||||
|
}
|
||||||
|
|
||||||
|
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"),
|
||||||
|
abi::OsMacos => InternedString::new("macos"),
|
||||||
|
abi::OsLinux => InternedString::new("linux"),
|
||||||
|
abi::OsAndroid => InternedString::new("android"),
|
||||||
|
abi::OsFreebsd => InternedString::new("freebsd"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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")
|
||||||
|
};
|
||||||
|
|
||||||
|
let fam = match sess.targ_cfg.os {
|
||||||
|
abi::OsWin32 => InternedString::new("windows"),
|
||||||
|
_ => 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_family"), fam),
|
||||||
|
mk(InternedString::new("target_arch"), InternedString::new(arch)),
|
||||||
|
mk(InternedString::new("target_endian"), InternedString::new(end)),
|
||||||
|
mk(InternedString::new("target_word_size"),
|
||||||
|
InternedString::new(wordsz))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_configuration(cfg: &mut ast::CrateConfig,
|
||||||
|
name: InternedString) {
|
||||||
|
if !cfg.iter().any(|mi| mi.name() == name) {
|
||||||
|
cfg.push(attr::mk_word_item(name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
|
||||||
|
// Combine the configuration requested by the session (command line) with
|
||||||
|
// some default and generated configuration items
|
||||||
|
let default_cfg = default_configuration(sess);
|
||||||
|
let mut user_cfg = sess.opts.cfg.clone();
|
||||||
|
// If the user wants a test runner, then add the test cfg
|
||||||
|
if sess.opts.test {
|
||||||
|
append_configuration(&mut user_cfg, InternedString::new("test"))
|
||||||
|
}
|
||||||
|
// If the user requested GC, then add the GC cfg
|
||||||
|
append_configuration(&mut user_cfg, if sess.opts.gc {
|
||||||
|
InternedString::new("gc")
|
||||||
|
} else {
|
||||||
|
InternedString::new("nogc")
|
||||||
|
});
|
||||||
|
user_cfg.move_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)] = &'static [
|
||||||
|
("mingw32", abi::OsWin32),
|
||||||
|
("win32", abi::OsWin32),
|
||||||
|
("darwin", abi::OsMacos),
|
||||||
|
("android", abi::OsAndroid),
|
||||||
|
("linux", abi::OsLinux),
|
||||||
|
("freebsd", abi::OsFreebsd)];
|
||||||
|
|
||||||
|
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)] = &'static [
|
||||||
|
("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),
|
||||||
|
|
||||||
|
("mips", abi::Mips)];
|
||||||
|
|
||||||
|
pub fn build_target_config(sopts: &Options) -> Config {
|
||||||
|
let os = match get_os(sopts.target_triple) {
|
||||||
|
Some(os) => os,
|
||||||
|
None => early_error("unknown operating system")
|
||||||
|
};
|
||||||
|
let arch = match get_arch(sopts.target_triple) {
|
||||||
|
Some(arch) => arch,
|
||||||
|
None => early_error("unknown architecture: " + sopts.target_triple)
|
||||||
|
};
|
||||||
|
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)
|
||||||
|
};
|
||||||
|
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)
|
||||||
|
};
|
||||||
|
Config {
|
||||||
|
os: os,
|
||||||
|
arch: arch,
|
||||||
|
target_strs: target_strs,
|
||||||
|
int_type: int_type,
|
||||||
|
uint_type: uint_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rustc command line options
|
||||||
|
pub fn optgroups() -> Vec<getopts::OptGroup> {
|
||||||
|
vec!(
|
||||||
|
optflag("h", "help", "Display this message"),
|
||||||
|
optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
|
||||||
|
optmulti("L", "", "Add a directory to the library search path", "PATH"),
|
||||||
|
optmulti("", "crate-type", "Comma separated list of types of crates
|
||||||
|
for the compiler to emit",
|
||||||
|
"[bin|lib|rlib|dylib|staticlib]"),
|
||||||
|
optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
|
||||||
|
"[asm|bc|ir|obj|link]"),
|
||||||
|
optflag("", "crate-id", "Output the crate id and exit"),
|
||||||
|
optflag("", "crate-name", "Output the crate name and exit"),
|
||||||
|
optflag("", "crate-file-name", "Output the file(s) that would be written if compilation \
|
||||||
|
continued and exit"),
|
||||||
|
optflag("g", "", "Equivalent to --debuginfo=2"),
|
||||||
|
optopt("", "debuginfo", "Emit DWARF debug info to the objects created:
|
||||||
|
0 = no debug info,
|
||||||
|
1 = line-tables only (for stacktraces and breakpoints),
|
||||||
|
2 = full debug info with variable and type information (same as -g)", "LEVEL"),
|
||||||
|
optflag("", "no-trans", "Run all passes except translation; no output"),
|
||||||
|
optflag("", "no-analysis",
|
||||||
|
"Parse and expand the source, but run no analysis and produce no output"),
|
||||||
|
optflag("O", "", "Equivalent to --opt-level=2"),
|
||||||
|
optopt("o", "", "Write output to <filename>", "FILENAME"),
|
||||||
|
optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
|
||||||
|
optopt( "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
|
||||||
|
optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
|
||||||
|
optflagopt("", "pretty",
|
||||||
|
"Pretty-print the input instead of compiling;
|
||||||
|
valid types are: normal (un-annotated source),
|
||||||
|
expanded (crates expanded),
|
||||||
|
typed (crates expanded, with type annotations),
|
||||||
|
or identified (fully parenthesized,
|
||||||
|
AST nodes and blocks with IDs)", "TYPE"),
|
||||||
|
optflagopt("", "dep-info",
|
||||||
|
"Output dependency info to <filename> after compiling, \
|
||||||
|
in a format suitable for use by Makefiles", "FILENAME"),
|
||||||
|
optopt("", "sysroot", "Override the system root", "PATH"),
|
||||||
|
optflag("", "test", "Build a test harness"),
|
||||||
|
optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
|
||||||
|
to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
|
||||||
|
for details)", "TRIPLE"),
|
||||||
|
optmulti("W", "warn", "Set lint warnings", "OPT"),
|
||||||
|
optmulti("A", "allow", "Set lint allowed", "OPT"),
|
||||||
|
optmulti("D", "deny", "Set lint denied", "OPT"),
|
||||||
|
optmulti("F", "forbid", "Set lint forbidden", "OPT"),
|
||||||
|
optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
|
||||||
|
optmulti("Z", "", "Set internal debugging options", "FLAG"),
|
||||||
|
optflag( "v", "version", "Print version info and exit")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Convert strings provided as --cfg [cfgspec] into a crate_cfg
|
||||||
|
fn parse_cfgspecs(cfgspecs: Vec<~str> ) -> ast::CrateConfig {
|
||||||
|
cfgspecs.move_iter().map(|s| {
|
||||||
|
parse::parse_meta_from_source_str("cfgspec".to_strbuf(),
|
||||||
|
s.to_strbuf(),
|
||||||
|
Vec::new(),
|
||||||
|
&parse::new_parse_sess())
|
||||||
|
}).collect::<ast::CrateConfig>()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
||||||
|
let mut crate_types: Vec<CrateType> = Vec::new();
|
||||||
|
let unparsed_crate_types = matches.opt_strs("crate-type");
|
||||||
|
for unparsed_crate_type in unparsed_crate_types.iter() {
|
||||||
|
for part in unparsed_crate_type.split(',') {
|
||||||
|
let new_part = match part {
|
||||||
|
"lib" => default_lib_output(),
|
||||||
|
"rlib" => CrateTypeRlib,
|
||||||
|
"staticlib" => CrateTypeStaticlib,
|
||||||
|
"dylib" => CrateTypeDylib,
|
||||||
|
"bin" => CrateTypeExecutable,
|
||||||
|
_ => early_error(format!("unknown crate type: `{}`", part))
|
||||||
|
};
|
||||||
|
crate_types.push(new_part)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let parse_only = matches.opt_present("parse-only");
|
||||||
|
let no_trans = matches.opt_present("no-trans");
|
||||||
|
let no_analysis = matches.opt_present("no-analysis");
|
||||||
|
|
||||||
|
let lint_levels = [lint::allow, lint::warn,
|
||||||
|
lint::deny, lint::forbid];
|
||||||
|
let mut lint_opts = Vec::new();
|
||||||
|
let lint_dict = lint::get_lint_dict();
|
||||||
|
for level in lint_levels.iter() {
|
||||||
|
let level_name = lint::level_to_str(*level);
|
||||||
|
|
||||||
|
let level_short = level_name.slice_chars(0, 1);
|
||||||
|
let level_short = level_short.to_ascii().to_upper().into_str();
|
||||||
|
let flags = matches.opt_strs(level_short).move_iter().collect::<Vec<_>>().append(
|
||||||
|
matches.opt_strs(level_name).as_slice());
|
||||||
|
for lint_name in flags.iter() {
|
||||||
|
let lint_name = lint_name.replace("-", "_");
|
||||||
|
match lint_dict.find_equiv(&lint_name) {
|
||||||
|
None => {
|
||||||
|
early_error(format!("unknown {} flag: {}",
|
||||||
|
level_name, lint_name));
|
||||||
|
}
|
||||||
|
Some(lint) => {
|
||||||
|
lint_opts.push((lint.lint, *level));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut debugging_opts = 0;
|
||||||
|
let debug_flags = matches.opt_strs("Z");
|
||||||
|
let debug_map = debugging_opts_map();
|
||||||
|
for debug_flag in debug_flags.iter() {
|
||||||
|
let mut this_bit = 0;
|
||||||
|
for tuple in debug_map.iter() {
|
||||||
|
let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
|
||||||
|
if *name == *debug_flag { this_bit = bit; break; }
|
||||||
|
}
|
||||||
|
if this_bit == 0 {
|
||||||
|
early_error(format!("unknown debug flag: {}", *debug_flag))
|
||||||
|
}
|
||||||
|
debugging_opts |= this_bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if debugging_opts & DEBUG_LLVM != 0 {
|
||||||
|
unsafe { llvm::LLVMSetDebug(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output_types = Vec::new();
|
||||||
|
if !parse_only && !no_trans {
|
||||||
|
let unparsed_output_types = matches.opt_strs("emit");
|
||||||
|
for unparsed_output_type in unparsed_output_types.iter() {
|
||||||
|
for part in unparsed_output_type.split(',') {
|
||||||
|
let output_type = match part.as_slice() {
|
||||||
|
"asm" => link::OutputTypeAssembly,
|
||||||
|
"ir" => link::OutputTypeLlvmAssembly,
|
||||||
|
"bc" => link::OutputTypeBitcode,
|
||||||
|
"obj" => link::OutputTypeObject,
|
||||||
|
"link" => link::OutputTypeExe,
|
||||||
|
_ => early_error(format!("unknown emission type: `{}`", part))
|
||||||
|
};
|
||||||
|
output_types.push(output_type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
output_types.as_mut_slice().sort();
|
||||||
|
output_types.dedup();
|
||||||
|
if output_types.len() == 0 {
|
||||||
|
output_types.push(link::OutputTypeExe);
|
||||||
|
}
|
||||||
|
|
||||||
|
let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
|
||||||
|
let target = matches.opt_str("target").unwrap_or(driver::host_triple().to_owned());
|
||||||
|
let opt_level = {
|
||||||
|
if (debugging_opts & NO_OPT) != 0 {
|
||||||
|
No
|
||||||
|
} else if matches.opt_present("O") {
|
||||||
|
if matches.opt_present("opt-level") {
|
||||||
|
early_error("-O and --opt-level both provided");
|
||||||
|
}
|
||||||
|
Default
|
||||||
|
} else if matches.opt_present("opt-level") {
|
||||||
|
match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) {
|
||||||
|
None |
|
||||||
|
Some("0") => No,
|
||||||
|
Some("1") => Less,
|
||||||
|
Some("2") => Default,
|
||||||
|
Some("3") => Aggressive,
|
||||||
|
Some(arg) => {
|
||||||
|
early_error(format!("optimization level needs to be between 0-3 \
|
||||||
|
(instead was `{}`)", arg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
No
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let gc = debugging_opts & GC != 0;
|
||||||
|
let debuginfo = if matches.opt_present("g") {
|
||||||
|
if matches.opt_present("debuginfo") {
|
||||||
|
early_error("-g and --debuginfo both provided");
|
||||||
|
}
|
||||||
|
FullDebugInfo
|
||||||
|
} else if matches.opt_present("debuginfo") {
|
||||||
|
match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) {
|
||||||
|
Some("0") => NoDebugInfo,
|
||||||
|
Some("1") => LimitedDebugInfo,
|
||||||
|
None |
|
||||||
|
Some("2") => FullDebugInfo,
|
||||||
|
Some(arg) => {
|
||||||
|
early_error(format!("optimization level needs to be between 0-3 \
|
||||||
|
(instead was `{}`)", arg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NoDebugInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
|
||||||
|
Path::new(s.as_slice())
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
let cfg = parse_cfgspecs(matches.opt_strs("cfg").move_iter().collect());
|
||||||
|
let test = matches.opt_present("test");
|
||||||
|
let write_dependency_info = (matches.opt_present("dep-info"),
|
||||||
|
matches.opt_str("dep-info").map(|p| Path::new(p)));
|
||||||
|
|
||||||
|
let print_metas = (matches.opt_present("crate-id"),
|
||||||
|
matches.opt_present("crate-name"),
|
||||||
|
matches.opt_present("crate-file-name"));
|
||||||
|
let cg = build_codegen_options(matches);
|
||||||
|
|
||||||
|
Options {
|
||||||
|
crate_types: crate_types,
|
||||||
|
gc: gc,
|
||||||
|
optimize: opt_level,
|
||||||
|
debuginfo: debuginfo,
|
||||||
|
lint_opts: lint_opts,
|
||||||
|
output_types: output_types,
|
||||||
|
addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
|
||||||
|
maybe_sysroot: sysroot_opt,
|
||||||
|
target_triple: target,
|
||||||
|
cfg: cfg,
|
||||||
|
test: test,
|
||||||
|
parse_only: parse_only,
|
||||||
|
no_trans: no_trans,
|
||||||
|
no_analysis: no_analysis,
|
||||||
|
debugging_opts: debugging_opts,
|
||||||
|
write_dependency_info: write_dependency_info,
|
||||||
|
print_metas: print_metas,
|
||||||
|
cg: cg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
|
||||||
|
use driver::config::{build_configuration, optgroups, build_session_options};
|
||||||
|
use driver::session::build_session;
|
||||||
|
|
||||||
|
use getopts::getopts;
|
||||||
|
use syntax::attr;
|
||||||
|
use syntax::attr::AttrMetaMethods;
|
||||||
|
|
||||||
|
// When the user supplies --test we should implicitly supply --cfg test
|
||||||
|
#[test]
|
||||||
|
fn test_switch_implies_cfg_test() {
|
||||||
|
let matches =
|
||||||
|
&match getopts(["--test".to_owned()], optgroups().as_slice()) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(f) => fail!("test_switch_implies_cfg_test: {}", f.to_err_msg())
|
||||||
|
};
|
||||||
|
let sessopts = build_session_options(matches);
|
||||||
|
let sess = build_session(sessopts, None);
|
||||||
|
let cfg = build_configuration(&sess);
|
||||||
|
assert!((attr::contains_name(cfg.as_slice(), "test")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the user supplies --test and --cfg test, don't implicitly add
|
||||||
|
// another --cfg test
|
||||||
|
#[test]
|
||||||
|
fn test_switch_implies_cfg_test_unless_cfg_test() {
|
||||||
|
let matches =
|
||||||
|
&match getopts(["--test".to_owned(), "--cfg=test".to_owned()],
|
||||||
|
optgroups().as_slice()) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(f) => {
|
||||||
|
fail!("test_switch_implies_cfg_test_unless_cfg_test: {}",
|
||||||
|
f.to_err_msg());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let sessopts = build_session_options(matches);
|
||||||
|
let sess = build_session(sessopts, None);
|
||||||
|
let cfg = build_configuration(&sess);
|
||||||
|
let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
|
||||||
|
assert!(test_items.next().is_some());
|
||||||
|
assert!(test_items.next().is_none());
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,56 +10,89 @@
|
||||||
|
|
||||||
|
|
||||||
use back::link;
|
use back::link;
|
||||||
use back::{arm, x86, x86_64, mips};
|
use driver::session::Session;
|
||||||
use driver::session::{Aggressive, CrateTypeExecutable, CrateType,
|
use driver::config;
|
||||||
FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
|
||||||
use driver::session::{Session, No, Less, Default};
|
|
||||||
use driver::session;
|
|
||||||
use front;
|
use front;
|
||||||
use lib::llvm::llvm;
|
|
||||||
use lib::llvm::{ContextRef, ModuleRef};
|
use lib::llvm::{ContextRef, ModuleRef};
|
||||||
use metadata::common::LinkMeta;
|
use metadata::common::LinkMeta;
|
||||||
use metadata::{creader, filesearch};
|
use metadata::creader;
|
||||||
use metadata::cstore::CStore;
|
|
||||||
use metadata::creader::Loader;
|
use metadata::creader::Loader;
|
||||||
use metadata;
|
|
||||||
use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
|
use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
|
||||||
use middle::dependency_format;
|
use middle::dependency_format;
|
||||||
use middle;
|
use middle;
|
||||||
use util::common::time;
|
use util::common::time;
|
||||||
use util::ppaux;
|
use util::ppaux;
|
||||||
use util::nodemap::{NodeMap, NodeSet};
|
use util::nodemap::{NodeSet};
|
||||||
|
|
||||||
use serialize::{json, Encodable};
|
use serialize::{json, Encodable};
|
||||||
|
|
||||||
use std::cell::{Cell, RefCell};
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::fs;
|
use std::io::fs;
|
||||||
use std::io::MemReader;
|
use std::io::MemReader;
|
||||||
use std::os;
|
|
||||||
use getopts::{optopt, optmulti, optflag, optflagopt};
|
|
||||||
use getopts;
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::abi;
|
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::attr::{AttrMetaMethods};
|
use syntax::attr::{AttrMetaMethods};
|
||||||
use syntax::codemap;
|
|
||||||
use syntax::crateid::CrateId;
|
use syntax::crateid::CrateId;
|
||||||
use syntax::diagnostic;
|
|
||||||
use syntax::diagnostic::Emitter;
|
|
||||||
use syntax::ext::base::CrateLoader;
|
use syntax::ext::base::CrateLoader;
|
||||||
use syntax::parse;
|
use syntax::parse;
|
||||||
use syntax::parse::token::InternedString;
|
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
use syntax::print::{pp, pprust};
|
use syntax::print::{pp, pprust};
|
||||||
use syntax;
|
use syntax;
|
||||||
|
|
||||||
pub enum PpMode {
|
pub fn host_triple() -> &'static str {
|
||||||
PpmNormal,
|
// Get the host triple out of the build environment. This ensures that our
|
||||||
PpmExpanded,
|
// idea of the host triple is the same as for the set of libraries we've
|
||||||
PpmTyped,
|
// actually built. We can't just take LLVM's host triple because they
|
||||||
PpmIdentified,
|
// normalize all ix86 architectures to i386.
|
||||||
PpmExpandedIdentified
|
//
|
||||||
|
// Instead of grabbing the host triple (for the current host), we grab (at
|
||||||
|
// compile time) the target triple that this rustc is built with and
|
||||||
|
// calling that (at runtime) the host triple.
|
||||||
|
(option_env!("CFG_COMPILER_HOST_TRIPLE")).
|
||||||
|
expect("CFG_COMPILER_HOST_TRIPLE")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compile_input(sess: Session,
|
||||||
|
cfg: ast::CrateConfig,
|
||||||
|
input: &Input,
|
||||||
|
outdir: &Option<Path>,
|
||||||
|
output: &Option<Path>) {
|
||||||
|
// We need nested scopes here, because the intermediate results can keep
|
||||||
|
// large chunks of memory alive and we want to free them as soon as
|
||||||
|
// possible to keep the peak memory usage low
|
||||||
|
let (outputs, trans, sess) = {
|
||||||
|
let (outputs, expanded_crate, ast_map) = {
|
||||||
|
let krate = phase_1_parse_input(&sess, cfg, input);
|
||||||
|
if stop_after_phase_1(&sess) { return; }
|
||||||
|
let outputs = build_output_filenames(input,
|
||||||
|
outdir,
|
||||||
|
output,
|
||||||
|
krate.attrs.as_slice(),
|
||||||
|
&sess);
|
||||||
|
let loader = &mut Loader::new(&sess);
|
||||||
|
let id = link::find_crate_id(krate.attrs.as_slice(),
|
||||||
|
outputs.out_filestem);
|
||||||
|
let (expanded_crate, ast_map) = phase_2_configure_and_expand(&sess, loader,
|
||||||
|
krate, &id);
|
||||||
|
(outputs, expanded_crate, ast_map)
|
||||||
|
};
|
||||||
|
write_out_deps(&sess, input, &outputs, &expanded_crate);
|
||||||
|
|
||||||
|
if stop_after_phase_2(&sess) { return; }
|
||||||
|
|
||||||
|
let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
|
||||||
|
if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
|
||||||
|
let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate,
|
||||||
|
analysis, &outputs);
|
||||||
|
|
||||||
|
// Discard interned strings as they are no longer required.
|
||||||
|
token::get_ident_interner().clear();
|
||||||
|
|
||||||
|
(outputs, trans, tcx.sess)
|
||||||
|
};
|
||||||
|
phase_5_run_llvm_passes(&sess, &trans, &outputs);
|
||||||
|
if stop_after_phase_5(&sess) { return; }
|
||||||
|
phase_6_link_output(&sess, &trans, &outputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,78 +111,6 @@ pub fn source_name(input: &Input) -> ~str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_configuration(sess: &Session) ->
|
|
||||||
ast::CrateConfig {
|
|
||||||
let tos = match sess.targ_cfg.os {
|
|
||||||
abi::OsWin32 => InternedString::new("win32"),
|
|
||||||
abi::OsMacos => InternedString::new("macos"),
|
|
||||||
abi::OsLinux => InternedString::new("linux"),
|
|
||||||
abi::OsAndroid => InternedString::new("android"),
|
|
||||||
abi::OsFreebsd => InternedString::new("freebsd"),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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")
|
|
||||||
};
|
|
||||||
|
|
||||||
let fam = match sess.targ_cfg.os {
|
|
||||||
abi::OsWin32 => InternedString::new("windows"),
|
|
||||||
_ => 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_family"), fam),
|
|
||||||
mk(InternedString::new("target_arch"), InternedString::new(arch)),
|
|
||||||
mk(InternedString::new("target_endian"), InternedString::new(end)),
|
|
||||||
mk(InternedString::new("target_word_size"),
|
|
||||||
InternedString::new(wordsz))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_configuration(cfg: &mut ast::CrateConfig,
|
|
||||||
name: InternedString) {
|
|
||||||
if !cfg.iter().any(|mi| mi.name() == name) {
|
|
||||||
cfg.push(attr::mk_word_item(name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
|
|
||||||
// Combine the configuration requested by the session (command line) with
|
|
||||||
// some default and generated configuration items
|
|
||||||
let default_cfg = default_configuration(sess);
|
|
||||||
let mut user_cfg = sess.opts.cfg.clone();
|
|
||||||
// If the user wants a test runner, then add the test cfg
|
|
||||||
if sess.opts.test {
|
|
||||||
append_configuration(&mut user_cfg, InternedString::new("test"))
|
|
||||||
}
|
|
||||||
// If the user requested GC, then add the GC cfg
|
|
||||||
append_configuration(&mut user_cfg, if sess.opts.gc {
|
|
||||||
InternedString::new("gc")
|
|
||||||
} else {
|
|
||||||
InternedString::new("nogc")
|
|
||||||
});
|
|
||||||
user_cfg.move_iter().collect::<Vec<_>>().append(default_cfg.as_slice())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert strings provided as --cfg [cfgspec] into a crate_cfg
|
|
||||||
fn parse_cfgspecs(cfgspecs: Vec<~str> )
|
|
||||||
-> ast::CrateConfig {
|
|
||||||
cfgspecs.move_iter().map(|s| {
|
|
||||||
parse::parse_meta_from_source_str("cfgspec".to_strbuf(),
|
|
||||||
s.to_strbuf(),
|
|
||||||
Vec::new(),
|
|
||||||
&parse::new_parse_sess())
|
|
||||||
}).collect::<ast::CrateConfig>()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Input {
|
pub enum Input {
|
||||||
/// Load source from file
|
/// Load source from file
|
||||||
FileInput(Path),
|
FileInput(Path),
|
||||||
|
@ -183,7 +144,7 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0 {
|
if sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0 {
|
||||||
let mut stdout = io::BufferedWriter::new(io::stdout());
|
let mut stdout = io::BufferedWriter::new(io::stdout());
|
||||||
let mut json = json::PrettyEncoder::new(&mut stdout);
|
let mut json = json::PrettyEncoder::new(&mut stdout);
|
||||||
// unwrapping so IoError isn't ignored
|
// unwrapping so IoError isn't ignored
|
||||||
|
@ -211,7 +172,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
||||||
-> (ast::Crate, syntax::ast_map::Map) {
|
-> (ast::Crate, syntax::ast_map::Map) {
|
||||||
let time_passes = sess.time_passes();
|
let time_passes = sess.time_passes();
|
||||||
|
|
||||||
*sess.crate_types.borrow_mut() = session::collect_crate_types(sess, krate.attrs.as_slice());
|
*sess.crate_types.borrow_mut() = collect_crate_types(sess, krate.attrs.as_slice());
|
||||||
|
|
||||||
time(time_passes, "gated feature checking", (), |_|
|
time(time_passes, "gated feature checking", (), |_|
|
||||||
front::feature_gate::check_crate(sess, &krate));
|
front::feature_gate::check_crate(sess, &krate));
|
||||||
|
@ -262,7 +223,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
||||||
let (krate, map) = time(time_passes, "assinging node ids and indexing ast", krate, |krate|
|
let (krate, map) = time(time_passes, "assinging node ids and indexing ast", krate, |krate|
|
||||||
front::assign_node_ids_and_map::assign_node_ids_and_map(sess, krate));
|
front::assign_node_ids_and_map::assign_node_ids_and_map(sess, krate));
|
||||||
|
|
||||||
if sess.opts.debugging_opts & session::AST_JSON != 0 {
|
if sess.opts.debugging_opts & config::AST_JSON != 0 {
|
||||||
let mut stdout = io::BufferedWriter::new(io::stdout());
|
let mut stdout = io::BufferedWriter::new(io::stdout());
|
||||||
let mut json = json::PrettyEncoder::new(&mut stdout);
|
let mut json = json::PrettyEncoder::new(&mut stdout);
|
||||||
// unwrapping so IoError isn't ignored
|
// unwrapping so IoError isn't ignored
|
||||||
|
@ -466,7 +427,7 @@ pub fn stop_after_phase_1(sess: &Session) -> bool {
|
||||||
if sess.show_span() {
|
if sess.show_span() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0;
|
return sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop_after_phase_2(sess: &Session) -> bool {
|
pub fn stop_after_phase_2(sess: &Session) -> bool {
|
||||||
|
@ -474,7 +435,7 @@ pub fn stop_after_phase_2(sess: &Session) -> bool {
|
||||||
debug!("invoked with --no-analysis, returning early from compile_input");
|
debug!("invoked with --no-analysis, returning early from compile_input");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return sess.opts.debugging_opts & session::AST_JSON != 0;
|
return sess.opts.debugging_opts & config::AST_JSON != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop_after_phase_5(sess: &Session) -> bool {
|
pub fn stop_after_phase_5(sess: &Session) -> bool {
|
||||||
|
@ -547,46 +508,6 @@ fn write_out_deps(sess: &Session,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &Input,
|
|
||||||
outdir: &Option<Path>, output: &Option<Path>) {
|
|
||||||
// We need nested scopes here, because the intermediate results can keep
|
|
||||||
// large chunks of memory alive and we want to free them as soon as
|
|
||||||
// possible to keep the peak memory usage low
|
|
||||||
let (outputs, trans, sess) = {
|
|
||||||
let (outputs, expanded_crate, ast_map) = {
|
|
||||||
let krate = phase_1_parse_input(&sess, cfg, input);
|
|
||||||
if stop_after_phase_1(&sess) { return; }
|
|
||||||
let outputs = build_output_filenames(input,
|
|
||||||
outdir,
|
|
||||||
output,
|
|
||||||
krate.attrs.as_slice(),
|
|
||||||
&sess);
|
|
||||||
let loader = &mut Loader::new(&sess);
|
|
||||||
let id = link::find_crate_id(krate.attrs.as_slice(),
|
|
||||||
outputs.out_filestem);
|
|
||||||
let (expanded_crate, ast_map) = phase_2_configure_and_expand(&sess, loader,
|
|
||||||
krate, &id);
|
|
||||||
(outputs, expanded_crate, ast_map)
|
|
||||||
};
|
|
||||||
write_out_deps(&sess, input, &outputs, &expanded_crate);
|
|
||||||
|
|
||||||
if stop_after_phase_2(&sess) { return; }
|
|
||||||
|
|
||||||
let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
|
|
||||||
if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
|
|
||||||
let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate,
|
|
||||||
analysis, &outputs);
|
|
||||||
|
|
||||||
// Discard interned strings as they are no longer required.
|
|
||||||
token::get_ident_interner().clear();
|
|
||||||
|
|
||||||
(outputs, trans, tcx.sess)
|
|
||||||
};
|
|
||||||
phase_5_run_llvm_passes(&sess, &trans, &outputs);
|
|
||||||
if stop_after_phase_5(&sess) { return; }
|
|
||||||
phase_6_link_output(&sess, &trans, &outputs);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct IdentifiedAnnotation;
|
struct IdentifiedAnnotation;
|
||||||
|
|
||||||
impl pprust::PpAnn for IdentifiedAnnotation {
|
impl pprust::PpAnn for IdentifiedAnnotation {
|
||||||
|
@ -657,7 +578,7 @@ impl pprust::PpAnn for TypedAnnotation {
|
||||||
pub fn pretty_print_input(sess: Session,
|
pub fn pretty_print_input(sess: Session,
|
||||||
cfg: ast::CrateConfig,
|
cfg: ast::CrateConfig,
|
||||||
input: &Input,
|
input: &Input,
|
||||||
ppm: PpMode,
|
ppm: ::driver::PpMode,
|
||||||
ofile: Option<Path>) {
|
ofile: Option<Path>) {
|
||||||
let krate = phase_1_parse_input(&sess, cfg, input);
|
let krate = phase_1_parse_input(&sess, cfg, input);
|
||||||
let id = link::find_crate_id(krate.attrs.as_slice(), input.filestem());
|
let id = link::find_crate_id(krate.attrs.as_slice(), input.filestem());
|
||||||
|
@ -727,403 +648,58 @@ pub fn pretty_print_input(sess: Session,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_os(triple: &str) -> Option<abi::Os> {
|
pub fn collect_crate_types(session: &Session,
|
||||||
for &(name, os) in os_names.iter() {
|
attrs: &[ast::Attribute]) -> Vec<config::CrateType> {
|
||||||
if triple.contains(name) { return Some(os) }
|
// If we're generating a test executable, then ignore all other output
|
||||||
}
|
// styles at all other locations
|
||||||
None
|
if session.opts.test {
|
||||||
}
|
return vec!(config::CrateTypeExecutable)
|
||||||
static os_names : &'static [(&'static str, abi::Os)] = &'static [
|
|
||||||
("mingw32", abi::OsWin32),
|
|
||||||
("win32", abi::OsWin32),
|
|
||||||
("darwin", abi::OsMacos),
|
|
||||||
("android", abi::OsAndroid),
|
|
||||||
("linux", abi::OsLinux),
|
|
||||||
("freebsd", abi::OsFreebsd)];
|
|
||||||
|
|
||||||
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)] = &'static [
|
|
||||||
("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),
|
|
||||||
|
|
||||||
("mips", abi::Mips)];
|
|
||||||
|
|
||||||
pub fn build_target_config(sopts: &session::Options) -> session::Config {
|
|
||||||
let os = match get_os(sopts.target_triple) {
|
|
||||||
Some(os) => os,
|
|
||||||
None => early_error("unknown operating system")
|
|
||||||
};
|
|
||||||
let arch = match get_arch(sopts.target_triple) {
|
|
||||||
Some(arch) => arch,
|
|
||||||
None => early_error("unknown architecture: " + sopts.target_triple)
|
|
||||||
};
|
|
||||||
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)
|
|
||||||
};
|
|
||||||
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)
|
|
||||||
};
|
|
||||||
session::Config {
|
|
||||||
os: os,
|
|
||||||
arch: arch,
|
|
||||||
target_strs: target_strs,
|
|
||||||
int_type: int_type,
|
|
||||||
uint_type: uint_type,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn host_triple() -> &'static str {
|
|
||||||
// Get the host triple out of the build environment. This ensures that our
|
|
||||||
// idea of the host triple is the same as for the set of libraries we've
|
|
||||||
// actually built. We can't just take LLVM's host triple because they
|
|
||||||
// normalize all ix86 architectures to i386.
|
|
||||||
//
|
|
||||||
// Instead of grabbing the host triple (for the current host), we grab (at
|
|
||||||
// compile time) the target triple that this rustc is built with and
|
|
||||||
// calling that (at runtime) the host triple.
|
|
||||||
(option_env!("CFG_COMPILER_HOST_TRIPLE")).
|
|
||||||
expect("CFG_COMPILER_HOST_TRIPLE")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_session_options(matches: &getopts::Matches) -> session::Options {
|
|
||||||
let mut crate_types: Vec<CrateType> = Vec::new();
|
|
||||||
let unparsed_crate_types = matches.opt_strs("crate-type");
|
|
||||||
for unparsed_crate_type in unparsed_crate_types.iter() {
|
|
||||||
for part in unparsed_crate_type.split(',') {
|
|
||||||
let new_part = match part {
|
|
||||||
"lib" => session::default_lib_output(),
|
|
||||||
"rlib" => session::CrateTypeRlib,
|
|
||||||
"staticlib" => session::CrateTypeStaticlib,
|
|
||||||
"dylib" => session::CrateTypeDylib,
|
|
||||||
"bin" => session::CrateTypeExecutable,
|
|
||||||
_ => early_error(format!("unknown crate type: `{}`", part))
|
|
||||||
};
|
|
||||||
crate_types.push(new_part)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let parse_only = matches.opt_present("parse-only");
|
// Only check command line flags if present. If no types are specified by
|
||||||
let no_trans = matches.opt_present("no-trans");
|
// command line, then reuse the empty `base` Vec to hold the types that
|
||||||
let no_analysis = matches.opt_present("no-analysis");
|
// will be found in crate attributes.
|
||||||
|
let mut base = session.opts.crate_types.clone();
|
||||||
let lint_levels = [lint::allow, lint::warn,
|
if base.len() > 0 {
|
||||||
lint::deny, lint::forbid];
|
return base
|
||||||
let mut lint_opts = Vec::new();
|
|
||||||
let lint_dict = lint::get_lint_dict();
|
|
||||||
for level in lint_levels.iter() {
|
|
||||||
let level_name = lint::level_to_str(*level);
|
|
||||||
|
|
||||||
let level_short = level_name.slice_chars(0, 1);
|
|
||||||
let level_short = level_short.to_ascii().to_upper().into_str();
|
|
||||||
let flags = matches.opt_strs(level_short).move_iter().collect::<Vec<_>>().append(
|
|
||||||
matches.opt_strs(level_name).as_slice());
|
|
||||||
for lint_name in flags.iter() {
|
|
||||||
let lint_name = lint_name.replace("-", "_");
|
|
||||||
match lint_dict.find_equiv(&lint_name) {
|
|
||||||
None => {
|
|
||||||
early_error(format!("unknown {} flag: {}",
|
|
||||||
level_name, lint_name));
|
|
||||||
}
|
|
||||||
Some(lint) => {
|
|
||||||
lint_opts.push((lint.lint, *level));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut debugging_opts = 0;
|
|
||||||
let debug_flags = matches.opt_strs("Z");
|
|
||||||
let debug_map = session::debugging_opts_map();
|
|
||||||
for debug_flag in debug_flags.iter() {
|
|
||||||
let mut this_bit = 0;
|
|
||||||
for tuple in debug_map.iter() {
|
|
||||||
let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
|
|
||||||
if *name == *debug_flag { this_bit = bit; break; }
|
|
||||||
}
|
|
||||||
if this_bit == 0 {
|
|
||||||
early_error(format!("unknown debug flag: {}", *debug_flag))
|
|
||||||
}
|
|
||||||
debugging_opts |= this_bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if debugging_opts & session::DEBUG_LLVM != 0 {
|
|
||||||
unsafe { llvm::LLVMSetDebug(1); }
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut output_types = Vec::new();
|
|
||||||
if !parse_only && !no_trans {
|
|
||||||
let unparsed_output_types = matches.opt_strs("emit");
|
|
||||||
for unparsed_output_type in unparsed_output_types.iter() {
|
|
||||||
for part in unparsed_output_type.split(',') {
|
|
||||||
let output_type = match part.as_slice() {
|
|
||||||
"asm" => link::OutputTypeAssembly,
|
|
||||||
"ir" => link::OutputTypeLlvmAssembly,
|
|
||||||
"bc" => link::OutputTypeBitcode,
|
|
||||||
"obj" => link::OutputTypeObject,
|
|
||||||
"link" => link::OutputTypeExe,
|
|
||||||
_ => early_error(format!("unknown emission type: `{}`", part))
|
|
||||||
};
|
|
||||||
output_types.push(output_type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
output_types.as_mut_slice().sort();
|
|
||||||
output_types.dedup();
|
|
||||||
if output_types.len() == 0 {
|
|
||||||
output_types.push(link::OutputTypeExe);
|
|
||||||
}
|
|
||||||
|
|
||||||
let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
|
|
||||||
let target = matches.opt_str("target").unwrap_or(host_triple().to_owned());
|
|
||||||
let opt_level = {
|
|
||||||
if (debugging_opts & session::NO_OPT) != 0 {
|
|
||||||
No
|
|
||||||
} else if matches.opt_present("O") {
|
|
||||||
if matches.opt_present("opt-level") {
|
|
||||||
early_error("-O and --opt-level both provided");
|
|
||||||
}
|
|
||||||
Default
|
|
||||||
} else if matches.opt_present("opt-level") {
|
|
||||||
match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) {
|
|
||||||
None |
|
|
||||||
Some("0") => No,
|
|
||||||
Some("1") => Less,
|
|
||||||
Some("2") => Default,
|
|
||||||
Some("3") => Aggressive,
|
|
||||||
Some(arg) => {
|
|
||||||
early_error(format!("optimization level needs to be between 0-3 \
|
|
||||||
(instead was `{}`)", arg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
No
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let gc = debugging_opts & session::GC != 0;
|
|
||||||
let debuginfo = if matches.opt_present("g") {
|
|
||||||
if matches.opt_present("debuginfo") {
|
|
||||||
early_error("-g and --debuginfo both provided");
|
|
||||||
}
|
|
||||||
FullDebugInfo
|
|
||||||
} else if matches.opt_present("debuginfo") {
|
|
||||||
match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) {
|
|
||||||
Some("0") => NoDebugInfo,
|
|
||||||
Some("1") => LimitedDebugInfo,
|
|
||||||
None |
|
|
||||||
Some("2") => FullDebugInfo,
|
|
||||||
Some(arg) => {
|
|
||||||
early_error(format!("optimization level needs to be between 0-3 \
|
|
||||||
(instead was `{}`)", arg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
NoDebugInfo
|
let iter = attrs.iter().filter_map(|a| {
|
||||||
};
|
if a.name().equiv(&("crate_type")) {
|
||||||
|
match a.value_str() {
|
||||||
let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
|
Some(ref n) if n.equiv(&("rlib")) => Some(config::CrateTypeRlib),
|
||||||
Path::new(s.as_slice())
|
Some(ref n) if n.equiv(&("dylib")) => Some(config::CrateTypeDylib),
|
||||||
}).collect();
|
Some(ref n) if n.equiv(&("lib")) => {
|
||||||
|
Some(config::default_lib_output())
|
||||||
let cfg = parse_cfgspecs(matches.opt_strs("cfg").move_iter().collect());
|
}
|
||||||
let test = matches.opt_present("test");
|
Some(ref n) if n.equiv(&("staticlib")) => {
|
||||||
let write_dependency_info = (matches.opt_present("dep-info"),
|
Some(config::CrateTypeStaticlib)
|
||||||
matches.opt_str("dep-info").map(|p| Path::new(p)));
|
}
|
||||||
|
Some(ref n) if n.equiv(&("bin")) => Some(config::CrateTypeExecutable),
|
||||||
let print_metas = (matches.opt_present("crate-id"),
|
Some(_) => {
|
||||||
matches.opt_present("crate-name"),
|
session.add_lint(lint::UnknownCrateType,
|
||||||
matches.opt_present("crate-file-name"));
|
ast::CRATE_NODE_ID,
|
||||||
let cg = build_codegen_options(matches);
|
a.span,
|
||||||
|
"invalid `crate_type` value".to_owned());
|
||||||
session::Options {
|
None
|
||||||
crate_types: crate_types,
|
}
|
||||||
gc: gc,
|
_ => {
|
||||||
optimize: opt_level,
|
session.add_lint(lint::UnknownCrateType, ast::CRATE_NODE_ID,
|
||||||
debuginfo: debuginfo,
|
a.span, "`crate_type` requires a value".to_owned());
|
||||||
lint_opts: lint_opts,
|
None
|
||||||
output_types: output_types,
|
}
|
||||||
addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
|
|
||||||
maybe_sysroot: sysroot_opt,
|
|
||||||
target_triple: target,
|
|
||||||
cfg: cfg,
|
|
||||||
test: test,
|
|
||||||
parse_only: parse_only,
|
|
||||||
no_trans: no_trans,
|
|
||||||
no_analysis: no_analysis,
|
|
||||||
debugging_opts: debugging_opts,
|
|
||||||
write_dependency_info: write_dependency_info,
|
|
||||||
print_metas: print_metas,
|
|
||||||
cg: cg,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_codegen_options(matches: &getopts::Matches)
|
|
||||||
-> session::CodegenOptions
|
|
||||||
{
|
|
||||||
let mut cg = session::basic_codegen_options();
|
|
||||||
for option in matches.opt_strs("C").move_iter() {
|
|
||||||
let mut iter = option.splitn('=', 1);
|
|
||||||
let key = iter.next().unwrap();
|
|
||||||
let value = iter.next();
|
|
||||||
let option_to_lookup = key.replace("-", "_");
|
|
||||||
let mut found = false;
|
|
||||||
for &(candidate, setter, _) in session::CG_OPTIONS.iter() {
|
|
||||||
if option_to_lookup.as_slice() != candidate { continue }
|
|
||||||
if !setter(&mut cg, value) {
|
|
||||||
match value {
|
|
||||||
Some(..) => early_error(format!("codegen option `{}` takes \
|
|
||||||
no value", key)),
|
|
||||||
None => early_error(format!("codegen option `{0}` requires \
|
|
||||||
a value (-C {0}=<value>)",
|
|
||||||
key))
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
found = true;
|
});
|
||||||
break;
|
base.extend(iter);
|
||||||
}
|
if base.len() == 0 {
|
||||||
if !found {
|
base.push(config::CrateTypeExecutable);
|
||||||
early_error(format!("unknown codegen option: `{}`", key));
|
|
||||||
}
|
}
|
||||||
|
base.as_mut_slice().sort();
|
||||||
|
base.dedup();
|
||||||
|
return base;
|
||||||
}
|
}
|
||||||
return cg;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_session(sopts: session::Options,
|
|
||||||
local_crate_source_file: Option<Path>)
|
|
||||||
-> Session {
|
|
||||||
let codemap = codemap::CodeMap::new();
|
|
||||||
let diagnostic_handler =
|
|
||||||
diagnostic::default_handler();
|
|
||||||
let span_diagnostic_handler =
|
|
||||||
diagnostic::mk_span_handler(diagnostic_handler, codemap);
|
|
||||||
|
|
||||||
build_session_(sopts, local_crate_source_file, span_diagnostic_handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_session_(sopts: session::Options,
|
|
||||||
local_crate_source_file: Option<Path>,
|
|
||||||
span_diagnostic: diagnostic::SpanHandler)
|
|
||||||
-> Session {
|
|
||||||
let target_cfg = build_target_config(&sopts);
|
|
||||||
let p_s = parse::new_parse_sess_special_handler(span_diagnostic);
|
|
||||||
let default_sysroot = match sopts.maybe_sysroot {
|
|
||||||
Some(_) => None,
|
|
||||||
None => Some(filesearch::get_or_default_sysroot())
|
|
||||||
};
|
|
||||||
|
|
||||||
// Make the path absolute, if necessary
|
|
||||||
let local_crate_source_file = local_crate_source_file.map(|path|
|
|
||||||
if path.is_absolute() {
|
|
||||||
path.clone()
|
|
||||||
} else {
|
|
||||||
os::getcwd().join(path.clone())
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Session {
|
|
||||||
targ_cfg: target_cfg,
|
|
||||||
opts: sopts,
|
|
||||||
cstore: CStore::new(token::get_ident_interner()),
|
|
||||||
parse_sess: p_s,
|
|
||||||
// For a library crate, this is always none
|
|
||||||
entry_fn: RefCell::new(None),
|
|
||||||
entry_type: Cell::new(None),
|
|
||||||
macro_registrar_fn: Cell::new(None),
|
|
||||||
default_sysroot: default_sysroot,
|
|
||||||
local_crate_source_file: local_crate_source_file,
|
|
||||||
working_dir: os::getcwd(),
|
|
||||||
lints: RefCell::new(NodeMap::new()),
|
|
||||||
node_id: Cell::new(1),
|
|
||||||
crate_types: RefCell::new(Vec::new()),
|
|
||||||
features: front::feature_gate::Features::new(),
|
|
||||||
recursion_limit: Cell::new(64),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_pretty(sess: &Session, name: &str) -> PpMode {
|
|
||||||
match name {
|
|
||||||
"normal" => PpmNormal,
|
|
||||||
"expanded" => PpmExpanded,
|
|
||||||
"typed" => PpmTyped,
|
|
||||||
"expanded,identified" => PpmExpandedIdentified,
|
|
||||||
"identified" => PpmIdentified,
|
|
||||||
_ => {
|
|
||||||
sess.fatal("argument to `pretty` must be one of `normal`, \
|
|
||||||
`expanded`, `typed`, `identified`, \
|
|
||||||
or `expanded,identified`");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rustc command line options
|
|
||||||
pub fn optgroups() -> Vec<getopts::OptGroup> {
|
|
||||||
vec!(
|
|
||||||
optflag("h", "help", "Display this message"),
|
|
||||||
optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
|
|
||||||
optmulti("L", "", "Add a directory to the library search path", "PATH"),
|
|
||||||
optmulti("", "crate-type", "Comma separated list of types of crates for the compiler to emit",
|
|
||||||
"[bin|lib|rlib|dylib|staticlib]"),
|
|
||||||
optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
|
|
||||||
"[asm|bc|ir|obj|link]"),
|
|
||||||
optflag("", "crate-id", "Output the crate id and exit"),
|
|
||||||
optflag("", "crate-name", "Output the crate name and exit"),
|
|
||||||
optflag("", "crate-file-name", "Output the file(s) that would be written if compilation \
|
|
||||||
continued and exit"),
|
|
||||||
optflag("g", "", "Equivalent to --debuginfo=2"),
|
|
||||||
optopt("", "debuginfo", "Emit DWARF debug info to the objects created:
|
|
||||||
0 = no debug info,
|
|
||||||
1 = line-tables only (for stacktraces and breakpoints),
|
|
||||||
2 = full debug info with variable and type information (same as -g)", "LEVEL"),
|
|
||||||
optflag("", "no-trans", "Run all passes except translation; no output"),
|
|
||||||
optflag("", "no-analysis",
|
|
||||||
"Parse and expand the source, but run no analysis and produce no output"),
|
|
||||||
optflag("O", "", "Equivalent to --opt-level=2"),
|
|
||||||
optopt("o", "", "Write output to <filename>", "FILENAME"),
|
|
||||||
optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
|
|
||||||
optopt( "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
|
|
||||||
optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
|
|
||||||
optflagopt("", "pretty",
|
|
||||||
"Pretty-print the input instead of compiling;
|
|
||||||
valid types are: normal (un-annotated source),
|
|
||||||
expanded (crates expanded),
|
|
||||||
typed (crates expanded, with type annotations),
|
|
||||||
or identified (fully parenthesized,
|
|
||||||
AST nodes and blocks with IDs)", "TYPE"),
|
|
||||||
optflagopt("", "dep-info",
|
|
||||||
"Output dependency info to <filename> after compiling, \
|
|
||||||
in a format suitable for use by Makefiles", "FILENAME"),
|
|
||||||
optopt("", "sysroot", "Override the system root", "PATH"),
|
|
||||||
optflag("", "test", "Build a test harness"),
|
|
||||||
optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
|
|
||||||
to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
|
|
||||||
for details)", "TRIPLE"),
|
|
||||||
optmulti("W", "warn", "Set lint warnings", "OPT"),
|
|
||||||
optmulti("A", "allow", "Set lint allowed", "OPT"),
|
|
||||||
optmulti("D", "deny", "Set lint denied", "OPT"),
|
|
||||||
optmulti("F", "forbid", "Set lint forbidden", "OPT"),
|
|
||||||
optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
|
|
||||||
optmulti("Z", "", "Set internal debugging options", "FLAG"),
|
|
||||||
optflag( "v", "version", "Print version info and exit"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OutputFilenames {
|
pub struct OutputFilenames {
|
||||||
|
@ -1209,60 +785,3 @@ pub fn build_output_filenames(input: &Input,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn early_error(msg: &str) -> ! {
|
|
||||||
let mut emitter = diagnostic::EmitterWriter::stderr();
|
|
||||||
emitter.emit(None, msg, diagnostic::Fatal);
|
|
||||||
fail!(diagnostic::FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn list_metadata(sess: &Session, path: &Path,
|
|
||||||
out: &mut io::Writer) -> io::IoResult<()> {
|
|
||||||
metadata::loader::list_file_metadata(
|
|
||||||
session::sess_os_to_meta_os(sess.targ_cfg.os), path, out)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
|
|
||||||
use driver::driver::{build_configuration, build_session};
|
|
||||||
use driver::driver::{build_session_options, optgroups};
|
|
||||||
|
|
||||||
use getopts::getopts;
|
|
||||||
use syntax::attr;
|
|
||||||
use syntax::attr::AttrMetaMethods;
|
|
||||||
|
|
||||||
// When the user supplies --test we should implicitly supply --cfg test
|
|
||||||
#[test]
|
|
||||||
fn test_switch_implies_cfg_test() {
|
|
||||||
let matches =
|
|
||||||
&match getopts(["--test".to_owned()], optgroups().as_slice()) {
|
|
||||||
Ok(m) => m,
|
|
||||||
Err(f) => fail!("test_switch_implies_cfg_test: {}", f.to_err_msg())
|
|
||||||
};
|
|
||||||
let sessopts = build_session_options(matches);
|
|
||||||
let sess = build_session(sessopts, None);
|
|
||||||
let cfg = build_configuration(&sess);
|
|
||||||
assert!((attr::contains_name(cfg.as_slice(), "test")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// When the user supplies --test and --cfg test, don't implicitly add
|
|
||||||
// another --cfg test
|
|
||||||
#[test]
|
|
||||||
fn test_switch_implies_cfg_test_unless_cfg_test() {
|
|
||||||
let matches =
|
|
||||||
&match getopts(["--test".to_owned(), "--cfg=test".to_owned()],
|
|
||||||
optgroups().as_slice()) {
|
|
||||||
Ok(m) => m,
|
|
||||||
Err(f) => {
|
|
||||||
fail!("test_switch_implies_cfg_test_unless_cfg_test: {}",
|
|
||||||
f.to_err_msg());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let sessopts = build_session_options(matches);
|
|
||||||
let sess = build_session(sessopts, None);
|
|
||||||
let cfg = build_configuration(&sess);
|
|
||||||
let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
|
|
||||||
assert!(test_items.next().is_some());
|
|
||||||
assert!(test_items.next().is_none());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,5 +10,391 @@
|
||||||
|
|
||||||
pub use syntax::diagnostic;
|
pub use syntax::diagnostic;
|
||||||
|
|
||||||
|
use back::link;
|
||||||
|
use driver::driver::{Input, FileInput, StrInput};
|
||||||
|
use driver::session::{Session, build_session};
|
||||||
|
use middle::lint;
|
||||||
|
use metadata;
|
||||||
|
|
||||||
|
use std::any::AnyRefExt;
|
||||||
|
use std::cmp;
|
||||||
|
use std::io;
|
||||||
|
use std::os;
|
||||||
|
use std::str;
|
||||||
|
use std::task::TaskBuilder;
|
||||||
|
|
||||||
|
use syntax::ast;
|
||||||
|
use syntax::parse;
|
||||||
|
use syntax::diagnostic::Emitter;
|
||||||
|
|
||||||
|
use getopts;
|
||||||
|
|
||||||
|
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
pub mod session;
|
pub mod session;
|
||||||
|
pub mod config;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn main_args(args: &[~str]) -> int {
|
||||||
|
let owned_args = args.to_owned();
|
||||||
|
monitor(proc() run_compiler(owned_args));
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
static BUG_REPORT_URL: &'static str =
|
||||||
|
"http://static.rust-lang.org/doc/master/complement-bugreport.html";
|
||||||
|
|
||||||
|
fn run_compiler(args: &[~str]) {
|
||||||
|
let matches = match handle_options(Vec::from_slice(args)) {
|
||||||
|
Some(matches) => matches,
|
||||||
|
None => return
|
||||||
|
};
|
||||||
|
|
||||||
|
let (input, input_file_path) = match matches.free.len() {
|
||||||
|
0u => early_error("no input filename given"),
|
||||||
|
1u => {
|
||||||
|
let ifile = matches.free.get(0).as_slice();
|
||||||
|
if ifile == "-" {
|
||||||
|
let contents = io::stdin().read_to_end().unwrap();
|
||||||
|
let src = str::from_utf8(contents.as_slice()).unwrap().to_owned();
|
||||||
|
(StrInput(src), None)
|
||||||
|
} else {
|
||||||
|
(FileInput(Path::new(ifile)), Some(Path::new(ifile)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => early_error("multiple input filenames provided")
|
||||||
|
};
|
||||||
|
|
||||||
|
let sopts = config::build_session_options(&matches);
|
||||||
|
let sess = build_session(sopts, input_file_path);
|
||||||
|
let cfg = config::build_configuration(&sess);
|
||||||
|
let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
|
||||||
|
let ofile = matches.opt_str("o").map(|o| Path::new(o));
|
||||||
|
|
||||||
|
let pretty = matches.opt_default("pretty", "normal").map(|a| {
|
||||||
|
parse_pretty(&sess, a)
|
||||||
|
});
|
||||||
|
match pretty {
|
||||||
|
Some::<PpMode>(ppm) => {
|
||||||
|
driver::pretty_print_input(sess, cfg, &input, ppm, ofile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
None::<PpMode> => {/* continue */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = matches.opt_strs("Z");
|
||||||
|
if r.contains(&("ls".to_owned())) {
|
||||||
|
match input {
|
||||||
|
FileInput(ref ifile) => {
|
||||||
|
let mut stdout = io::stdout();
|
||||||
|
list_metadata(&sess, &(*ifile), &mut stdout).unwrap();
|
||||||
|
}
|
||||||
|
StrInput(_) => {
|
||||||
|
early_error("can not list metadata for stdin");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if print_crate_info(&sess, &input, &odir, &ofile) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
driver::compile_input(sess, cfg, &input, &odir, &ofile);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn version(argv0: &str) {
|
||||||
|
let vers = match option_env!("CFG_VERSION") {
|
||||||
|
Some(vers) => vers,
|
||||||
|
None => "unknown version"
|
||||||
|
};
|
||||||
|
println!("{} {}", argv0, vers);
|
||||||
|
println!("host: {}", driver::host_triple());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(argv0: &str) {
|
||||||
|
let message = format!("Usage: {} [OPTIONS] INPUT", argv0);
|
||||||
|
println!("{}\n\
|
||||||
|
Additional help:
|
||||||
|
-C help Print codegen options
|
||||||
|
-W help Print 'lint' options and default settings
|
||||||
|
-Z help Print internal options for debugging rustc\n",
|
||||||
|
getopts::usage(message, config::optgroups().as_slice()));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn describe_warnings() {
|
||||||
|
println!("
|
||||||
|
Available lint options:
|
||||||
|
-W <foo> Warn about <foo>
|
||||||
|
-A <foo> Allow <foo>
|
||||||
|
-D <foo> Deny <foo>
|
||||||
|
-F <foo> Forbid <foo> (deny, and deny all overrides)
|
||||||
|
");
|
||||||
|
|
||||||
|
let lint_dict = lint::get_lint_dict();
|
||||||
|
let mut lint_dict = lint_dict.move_iter()
|
||||||
|
.map(|(k, v)| (v, k))
|
||||||
|
.collect::<Vec<(lint::LintSpec, &'static str)> >();
|
||||||
|
lint_dict.as_mut_slice().sort();
|
||||||
|
|
||||||
|
let mut max_key = 0;
|
||||||
|
for &(_, name) in lint_dict.iter() {
|
||||||
|
max_key = cmp::max(name.len(), max_key);
|
||||||
|
}
|
||||||
|
fn padded(max: uint, s: &str) -> ~str {
|
||||||
|
" ".repeat(max - s.len()) + s
|
||||||
|
}
|
||||||
|
println!("\nAvailable lint checks:\n");
|
||||||
|
println!(" {} {:7.7s} {}",
|
||||||
|
padded(max_key, "name"), "default", "meaning");
|
||||||
|
println!(" {} {:7.7s} {}\n",
|
||||||
|
padded(max_key, "----"), "-------", "-------");
|
||||||
|
for (spec, name) in lint_dict.move_iter() {
|
||||||
|
let name = name.replace("_", "-");
|
||||||
|
println!(" {} {:7.7s} {}",
|
||||||
|
padded(max_key, name),
|
||||||
|
lint::level_to_str(spec.default),
|
||||||
|
spec.desc);
|
||||||
|
}
|
||||||
|
println!("");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn describe_debug_flags() {
|
||||||
|
println!("\nAvailable debug options:\n");
|
||||||
|
let r = config::debugging_opts_map();
|
||||||
|
for tuple in r.iter() {
|
||||||
|
match *tuple {
|
||||||
|
(ref name, ref desc, _) => {
|
||||||
|
println!(" -Z {:>20s} -- {}", *name, *desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn describe_codegen_flags() {
|
||||||
|
println!("\nAvailable codegen options:\n");
|
||||||
|
let mut cg = config::basic_codegen_options();
|
||||||
|
for &(name, parser, desc) in config::CG_OPTIONS.iter() {
|
||||||
|
// we invoke the parser function on `None` to see if this option needs
|
||||||
|
// an argument or not.
|
||||||
|
let (width, extra) = if parser(&mut cg, None) {
|
||||||
|
(25, "")
|
||||||
|
} else {
|
||||||
|
(21, "=val")
|
||||||
|
};
|
||||||
|
println!(" -C {:>width$s}{} -- {}", name.replace("_", "-"),
|
||||||
|
extra, desc, width=width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process command line options. Emits messages as appropirate.If compilation
|
||||||
|
/// should continue, returns a getopts::Matches object parsed from args, otherwise
|
||||||
|
/// returns None.
|
||||||
|
pub fn handle_options(mut args: Vec<~str>) -> Option<getopts::Matches> {
|
||||||
|
let binary = args.shift().unwrap();
|
||||||
|
|
||||||
|
if args.is_empty() { usage(binary); return None; }
|
||||||
|
|
||||||
|
let matches =
|
||||||
|
match getopts::getopts(args.as_slice(), config::optgroups().as_slice()) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(f) => {
|
||||||
|
early_error(f.to_err_msg());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if matches.opt_present("h") || matches.opt_present("help") {
|
||||||
|
usage(binary);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let lint_flags = matches.opt_strs("W").move_iter().collect::<Vec<_>>().append(
|
||||||
|
matches.opt_strs("warn").as_slice());
|
||||||
|
if lint_flags.iter().any(|x| x == &"help".to_owned()) {
|
||||||
|
describe_warnings();
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = matches.opt_strs("Z");
|
||||||
|
if r.iter().any(|x| x == &"help".to_owned()) {
|
||||||
|
describe_debug_flags();
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cg_flags = matches.opt_strs("C");
|
||||||
|
if cg_flags.iter().any(|x| x == &"help".to_owned()) {
|
||||||
|
describe_codegen_flags();
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if cg_flags.contains(&"passes=list".to_owned()) {
|
||||||
|
unsafe { ::lib::llvm::llvm::LLVMRustPrintPasses(); }
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches.opt_present("v") || matches.opt_present("version") {
|
||||||
|
version(binary);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(matches)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_crate_info(sess: &Session,
|
||||||
|
input: &Input,
|
||||||
|
odir: &Option<Path>,
|
||||||
|
ofile: &Option<Path>)
|
||||||
|
-> bool {
|
||||||
|
let (crate_id, crate_name, crate_file_name) = sess.opts.print_metas;
|
||||||
|
// these nasty nested conditions are to avoid doing extra work
|
||||||
|
if crate_id || crate_name || crate_file_name {
|
||||||
|
let attrs = parse_crate_attrs(sess, input);
|
||||||
|
let t_outputs = driver::build_output_filenames(input, odir, ofile,
|
||||||
|
attrs.as_slice(), sess);
|
||||||
|
let id = link::find_crate_id(attrs.as_slice(), t_outputs.out_filestem);
|
||||||
|
|
||||||
|
if crate_id {
|
||||||
|
println!("{}", id.to_str());
|
||||||
|
}
|
||||||
|
if crate_name {
|
||||||
|
println!("{}", id.name);
|
||||||
|
}
|
||||||
|
if crate_file_name {
|
||||||
|
let crate_types = driver::collect_crate_types(sess, attrs.as_slice());
|
||||||
|
for &style in crate_types.iter() {
|
||||||
|
let fname = link::filename_for_input(sess, style, &id,
|
||||||
|
&t_outputs.with_extension(""));
|
||||||
|
println!("{}", fname.filename_display());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum PpMode {
|
||||||
|
PpmNormal,
|
||||||
|
PpmExpanded,
|
||||||
|
PpmTyped,
|
||||||
|
PpmIdentified,
|
||||||
|
PpmExpandedIdentified
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_pretty(sess: &Session, name: &str) -> PpMode {
|
||||||
|
match name {
|
||||||
|
"normal" => PpmNormal,
|
||||||
|
"expanded" => PpmExpanded,
|
||||||
|
"typed" => PpmTyped,
|
||||||
|
"expanded,identified" => PpmExpandedIdentified,
|
||||||
|
"identified" => PpmIdentified,
|
||||||
|
_ => {
|
||||||
|
sess.fatal("argument to `pretty` must be one of `normal`, \
|
||||||
|
`expanded`, `typed`, `identified`, \
|
||||||
|
or `expanded,identified`");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_crate_attrs(sess: &Session, input: &Input) ->
|
||||||
|
Vec<ast::Attribute> {
|
||||||
|
let result = match *input {
|
||||||
|
FileInput(ref ifile) => {
|
||||||
|
parse::parse_crate_attrs_from_file(ifile,
|
||||||
|
Vec::new(),
|
||||||
|
&sess.parse_sess)
|
||||||
|
}
|
||||||
|
StrInput(ref src) => {
|
||||||
|
parse::parse_crate_attrs_from_source_str(
|
||||||
|
driver::anon_src().to_strbuf(),
|
||||||
|
src.to_strbuf(),
|
||||||
|
Vec::new(),
|
||||||
|
&sess.parse_sess)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
result.move_iter().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn early_error(msg: &str) -> ! {
|
||||||
|
let mut emitter = diagnostic::EmitterWriter::stderr();
|
||||||
|
emitter.emit(None, msg, diagnostic::Fatal);
|
||||||
|
fail!(diagnostic::FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run a procedure which will detect failures in the compiler and print nicer
|
||||||
|
/// error messages rather than just failing the test.
|
||||||
|
///
|
||||||
|
/// The diagnostic emitter yielded to the procedure should be used for reporting
|
||||||
|
/// errors of the compiler.
|
||||||
|
fn monitor(f: proc():Send) {
|
||||||
|
// FIXME: This is a hack for newsched since it doesn't support split stacks.
|
||||||
|
// rustc needs a lot of stack! When optimizations are disabled, it needs
|
||||||
|
// even *more* stack than usual as well.
|
||||||
|
#[cfg(rtopt)]
|
||||||
|
static STACK_SIZE: uint = 6000000; // 6MB
|
||||||
|
#[cfg(not(rtopt))]
|
||||||
|
static STACK_SIZE: uint = 20000000; // 20MB
|
||||||
|
|
||||||
|
let mut task_builder = TaskBuilder::new().named("rustc");
|
||||||
|
|
||||||
|
// FIXME: Hacks on hacks. If the env is trying to override the stack size
|
||||||
|
// then *don't* set it explicitly.
|
||||||
|
if os::getenv("RUST_MIN_STACK").is_none() {
|
||||||
|
task_builder.opts.stack_size = Some(STACK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
let w = io::ChanWriter::new(tx);
|
||||||
|
let mut r = io::ChanReader::new(rx);
|
||||||
|
|
||||||
|
match task_builder.try(proc() {
|
||||||
|
io::stdio::set_stderr(box w);
|
||||||
|
f()
|
||||||
|
}) {
|
||||||
|
Ok(()) => { /* fallthrough */ }
|
||||||
|
Err(value) => {
|
||||||
|
// Task failed without emitting a fatal diagnostic
|
||||||
|
if !value.is::<diagnostic::FatalError>() {
|
||||||
|
let mut emitter = diagnostic::EmitterWriter::stderr();
|
||||||
|
|
||||||
|
// a .span_bug or .bug call has already printed what
|
||||||
|
// it wants to print.
|
||||||
|
if !value.is::<diagnostic::ExplicitBug>() {
|
||||||
|
emitter.emit(
|
||||||
|
None,
|
||||||
|
"unexpected failure",
|
||||||
|
diagnostic::Bug);
|
||||||
|
}
|
||||||
|
|
||||||
|
let xs = [
|
||||||
|
"the compiler hit an unexpected failure path. this is a bug.".to_owned(),
|
||||||
|
"we would appreciate a bug report: " + BUG_REPORT_URL,
|
||||||
|
"run with `RUST_BACKTRACE=1` for a backtrace".to_owned(),
|
||||||
|
];
|
||||||
|
for note in xs.iter() {
|
||||||
|
emitter.emit(None, *note, diagnostic::Note)
|
||||||
|
}
|
||||||
|
|
||||||
|
match r.read_to_str() {
|
||||||
|
Ok(s) => println!("{}", s),
|
||||||
|
Err(e) => emitter.emit(None,
|
||||||
|
format!("failed to read internal stderr: {}", e),
|
||||||
|
diagnostic::Error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fail so the process returns a failure code, but don't pollute the
|
||||||
|
// output with some unnecessary failure messages, we've already
|
||||||
|
// printed everything that we needed to.
|
||||||
|
io::stdio::set_stderr(box io::util::NullWriter);
|
||||||
|
fail!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,179 +9,34 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
|
||||||
use back::target_strs;
|
use driver::config;
|
||||||
use back;
|
use driver::driver;
|
||||||
use driver::driver::host_triple;
|
|
||||||
use front;
|
use front;
|
||||||
|
use metadata::cstore::CStore;
|
||||||
use metadata::filesearch;
|
use metadata::filesearch;
|
||||||
use metadata;
|
|
||||||
use middle::lint;
|
use middle::lint;
|
||||||
use util::nodemap::NodeMap;
|
use util::nodemap::NodeMap;
|
||||||
|
|
||||||
use syntax::attr::AttrMetaMethods;
|
|
||||||
use syntax::ast::NodeId;
|
use syntax::ast::NodeId;
|
||||||
use syntax::ast::{IntTy, UintTy};
|
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::diagnostic;
|
use syntax::diagnostic;
|
||||||
|
use syntax::parse;
|
||||||
|
use syntax::parse::token;
|
||||||
use syntax::parse::ParseSess;
|
use syntax::parse::ParseSess;
|
||||||
use syntax::{abi, ast, codemap};
|
use syntax::{ast, codemap};
|
||||||
|
|
||||||
|
use std::os;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use collections::HashSet;
|
|
||||||
|
|
||||||
pub struct Config {
|
|
||||||
pub os: abi::Os,
|
|
||||||
pub arch: abi::Architecture,
|
|
||||||
pub target_strs: target_strs::t,
|
|
||||||
pub int_type: IntTy,
|
|
||||||
pub uint_type: UintTy,
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! debugging_opts(
|
|
||||||
([ $opt:ident ] $cnt:expr ) => (
|
|
||||||
pub static $opt: u64 = 1 << $cnt;
|
|
||||||
);
|
|
||||||
([ $opt:ident, $($rest:ident),* ] $cnt:expr ) => (
|
|
||||||
pub static $opt: u64 = 1 << $cnt;
|
|
||||||
debugging_opts!([ $($rest),* ] $cnt + 1)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
debugging_opts!(
|
|
||||||
[
|
|
||||||
VERBOSE,
|
|
||||||
TIME_PASSES,
|
|
||||||
COUNT_LLVM_INSNS,
|
|
||||||
TIME_LLVM_PASSES,
|
|
||||||
TRANS_STATS,
|
|
||||||
ASM_COMMENTS,
|
|
||||||
NO_VERIFY,
|
|
||||||
BORROWCK_STATS,
|
|
||||||
NO_LANDING_PADS,
|
|
||||||
DEBUG_LLVM,
|
|
||||||
SHOW_SPAN,
|
|
||||||
COUNT_TYPE_SIZES,
|
|
||||||
META_STATS,
|
|
||||||
NO_OPT,
|
|
||||||
GC,
|
|
||||||
PRINT_LINK_ARGS,
|
|
||||||
PRINT_LLVM_PASSES,
|
|
||||||
LTO,
|
|
||||||
AST_JSON,
|
|
||||||
AST_JSON_NOEXPAND,
|
|
||||||
LS
|
|
||||||
]
|
|
||||||
0
|
|
||||||
)
|
|
||||||
|
|
||||||
pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
|
|
||||||
vec!(("verbose", "in general, enable more debug printouts", VERBOSE),
|
|
||||||
("time-passes", "measure time of each rustc pass", TIME_PASSES),
|
|
||||||
("count-llvm-insns", "count where LLVM \
|
|
||||||
instrs originate", COUNT_LLVM_INSNS),
|
|
||||||
("time-llvm-passes", "measure time of each LLVM pass",
|
|
||||||
TIME_LLVM_PASSES),
|
|
||||||
("trans-stats", "gather trans statistics", TRANS_STATS),
|
|
||||||
("asm-comments", "generate comments into the assembly (may change behavior)",
|
|
||||||
ASM_COMMENTS),
|
|
||||||
("no-verify", "skip LLVM verification", NO_VERIFY),
|
|
||||||
("borrowck-stats", "gather borrowck statistics", BORROWCK_STATS),
|
|
||||||
("no-landing-pads", "omit landing pads for unwinding",
|
|
||||||
NO_LANDING_PADS),
|
|
||||||
("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM),
|
|
||||||
("show-span", "show spans for compiler debugging", SHOW_SPAN),
|
|
||||||
("count-type-sizes", "count the sizes of aggregate types",
|
|
||||||
COUNT_TYPE_SIZES),
|
|
||||||
("meta-stats", "gather metadata statistics", META_STATS),
|
|
||||||
("no-opt", "do not optimize, even if -O is passed", NO_OPT),
|
|
||||||
("print-link-args", "Print the arguments passed to the linker",
|
|
||||||
PRINT_LINK_ARGS),
|
|
||||||
("gc", "Garbage collect shared data (experimental)", GC),
|
|
||||||
("print-llvm-passes",
|
|
||||||
"Prints the llvm optimization passes being run",
|
|
||||||
PRINT_LLVM_PASSES),
|
|
||||||
("lto", "Perform LLVM link-time optimizations", LTO),
|
|
||||||
("ast-json", "Print the AST as JSON and halt", AST_JSON),
|
|
||||||
("ast-json-noexpand", "Print the pre-expansion AST as JSON and halt", AST_JSON_NOEXPAND),
|
|
||||||
("ls", "List the symbols defined by a library crate", LS))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deriving(Clone, Eq)]
|
|
||||||
pub enum OptLevel {
|
|
||||||
No, // -O0
|
|
||||||
Less, // -O1
|
|
||||||
Default, // -O2
|
|
||||||
Aggressive // -O3
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deriving(Clone, Eq)]
|
|
||||||
pub enum DebugInfoLevel {
|
|
||||||
NoDebugInfo,
|
|
||||||
LimitedDebugInfo,
|
|
||||||
FullDebugInfo,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deriving(Clone)]
|
|
||||||
pub struct Options {
|
|
||||||
// The crate config requested for the session, which may be combined
|
|
||||||
// with additional crate configurations during the compile process
|
|
||||||
pub crate_types: Vec<CrateType>,
|
|
||||||
|
|
||||||
pub gc: bool,
|
|
||||||
pub optimize: OptLevel,
|
|
||||||
pub debuginfo: DebugInfoLevel,
|
|
||||||
pub lint_opts: Vec<(lint::Lint, lint::level)> ,
|
|
||||||
pub output_types: Vec<back::link::OutputType> ,
|
|
||||||
// This was mutable for rustpkg, which updates search paths based on the
|
|
||||||
// parsed code. It remains mutable in case its replacements wants to use
|
|
||||||
// this.
|
|
||||||
pub addl_lib_search_paths: RefCell<HashSet<Path>>,
|
|
||||||
pub maybe_sysroot: Option<Path>,
|
|
||||||
pub target_triple: ~str,
|
|
||||||
// User-specified cfg meta items. The compiler itself will add additional
|
|
||||||
// items to the crate config, and during parsing the entire crate config
|
|
||||||
// will be added to the crate AST node. This should not be used for
|
|
||||||
// anything except building the full crate config prior to parsing.
|
|
||||||
pub cfg: ast::CrateConfig,
|
|
||||||
pub test: bool,
|
|
||||||
pub parse_only: bool,
|
|
||||||
pub no_trans: bool,
|
|
||||||
pub no_analysis: bool,
|
|
||||||
pub debugging_opts: u64,
|
|
||||||
/// Whether to write dependency files. It's (enabled, optional filename).
|
|
||||||
pub write_dependency_info: (bool, Option<Path>),
|
|
||||||
/// Crate id-related things to maybe print. It's (crate_id, crate_name, crate_file_name).
|
|
||||||
pub print_metas: (bool, bool, bool),
|
|
||||||
pub cg: CodegenOptions,
|
|
||||||
}
|
|
||||||
|
|
||||||
// The type of entry function, so
|
|
||||||
// users can have their own entry
|
|
||||||
// functions that don't start a
|
|
||||||
// scheduler
|
|
||||||
#[deriving(Eq)]
|
|
||||||
pub enum EntryFnType {
|
|
||||||
EntryMain,
|
|
||||||
EntryStart,
|
|
||||||
EntryNone,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deriving(Eq, Ord, Clone, TotalOrd, TotalEq, Hash)]
|
|
||||||
pub enum CrateType {
|
|
||||||
CrateTypeExecutable,
|
|
||||||
CrateTypeDylib,
|
|
||||||
CrateTypeRlib,
|
|
||||||
CrateTypeStaticlib,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
pub targ_cfg: Config,
|
pub targ_cfg: config::Config,
|
||||||
pub opts: Options,
|
pub opts: config::Options,
|
||||||
pub cstore: metadata::cstore::CStore,
|
pub cstore: CStore,
|
||||||
pub parse_sess: ParseSess,
|
pub parse_sess: ParseSess,
|
||||||
// For a library crate, this is always none
|
// For a library crate, this is always none
|
||||||
pub entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
|
pub entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
|
||||||
pub entry_type: Cell<Option<EntryFnType>>,
|
pub entry_type: Cell<Option<config::EntryFnType>>,
|
||||||
pub macro_registrar_fn: Cell<Option<ast::NodeId>>,
|
pub macro_registrar_fn: Cell<Option<ast::NodeId>>,
|
||||||
pub default_sysroot: Option<Path>,
|
pub default_sysroot: Option<Path>,
|
||||||
// The name of the root source file of the crate, in the local file system. The path is always
|
// The name of the root source file of the crate, in the local file system. The path is always
|
||||||
|
@ -190,7 +45,7 @@ pub struct Session {
|
||||||
pub working_dir: Path,
|
pub working_dir: Path,
|
||||||
pub lints: RefCell<NodeMap<Vec<(lint::Lint, codemap::Span, ~str)>>>,
|
pub lints: RefCell<NodeMap<Vec<(lint::Lint, codemap::Span, ~str)>>>,
|
||||||
pub node_id: Cell<ast::NodeId>,
|
pub node_id: Cell<ast::NodeId>,
|
||||||
pub crate_types: RefCell<Vec<CrateType>>,
|
pub crate_types: RefCell<Vec<config::CrateType>>,
|
||||||
pub features: front::feature_gate::Features,
|
pub features: front::feature_gate::Features,
|
||||||
|
|
||||||
/// The maximum recursion limit for potentially infinitely recursive
|
/// The maximum recursion limit for potentially infinitely recursive
|
||||||
|
@ -289,33 +144,33 @@ impl Session {
|
||||||
pub fn impossible_case(&self, sp: Span, msg: &str) -> ! {
|
pub fn impossible_case(&self, sp: Span, msg: &str) -> ! {
|
||||||
self.span_bug(sp, format!("impossible case reached: {}", msg));
|
self.span_bug(sp, format!("impossible case reached: {}", msg));
|
||||||
}
|
}
|
||||||
pub fn verbose(&self) -> bool { self.debugging_opt(VERBOSE) }
|
pub fn verbose(&self) -> bool { self.debugging_opt(config::VERBOSE) }
|
||||||
pub fn time_passes(&self) -> bool { self.debugging_opt(TIME_PASSES) }
|
pub fn time_passes(&self) -> bool { self.debugging_opt(config::TIME_PASSES) }
|
||||||
pub fn count_llvm_insns(&self) -> bool {
|
pub fn count_llvm_insns(&self) -> bool {
|
||||||
self.debugging_opt(COUNT_LLVM_INSNS)
|
self.debugging_opt(config::COUNT_LLVM_INSNS)
|
||||||
}
|
}
|
||||||
pub fn count_type_sizes(&self) -> bool {
|
pub fn count_type_sizes(&self) -> bool {
|
||||||
self.debugging_opt(COUNT_TYPE_SIZES)
|
self.debugging_opt(config::COUNT_TYPE_SIZES)
|
||||||
}
|
}
|
||||||
pub fn time_llvm_passes(&self) -> bool {
|
pub fn time_llvm_passes(&self) -> bool {
|
||||||
self.debugging_opt(TIME_LLVM_PASSES)
|
self.debugging_opt(config::TIME_LLVM_PASSES)
|
||||||
}
|
}
|
||||||
pub fn trans_stats(&self) -> bool { self.debugging_opt(TRANS_STATS) }
|
pub fn trans_stats(&self) -> bool { self.debugging_opt(config::TRANS_STATS) }
|
||||||
pub fn meta_stats(&self) -> bool { self.debugging_opt(META_STATS) }
|
pub fn meta_stats(&self) -> bool { self.debugging_opt(config::META_STATS) }
|
||||||
pub fn asm_comments(&self) -> bool { self.debugging_opt(ASM_COMMENTS) }
|
pub fn asm_comments(&self) -> bool { self.debugging_opt(config::ASM_COMMENTS) }
|
||||||
pub fn no_verify(&self) -> bool { self.debugging_opt(NO_VERIFY) }
|
pub fn no_verify(&self) -> bool { self.debugging_opt(config::NO_VERIFY) }
|
||||||
pub fn borrowck_stats(&self) -> bool { self.debugging_opt(BORROWCK_STATS) }
|
pub fn borrowck_stats(&self) -> bool { self.debugging_opt(config::BORROWCK_STATS) }
|
||||||
pub fn print_llvm_passes(&self) -> bool {
|
pub fn print_llvm_passes(&self) -> bool {
|
||||||
self.debugging_opt(PRINT_LLVM_PASSES)
|
self.debugging_opt(config::PRINT_LLVM_PASSES)
|
||||||
}
|
}
|
||||||
pub fn lto(&self) -> bool {
|
pub fn lto(&self) -> bool {
|
||||||
self.debugging_opt(LTO)
|
self.debugging_opt(config::LTO)
|
||||||
}
|
}
|
||||||
pub fn no_landing_pads(&self) -> bool {
|
pub fn no_landing_pads(&self) -> bool {
|
||||||
self.debugging_opt(NO_LANDING_PADS)
|
self.debugging_opt(config::NO_LANDING_PADS)
|
||||||
}
|
}
|
||||||
pub fn show_span(&self) -> bool {
|
pub fn show_span(&self) -> bool {
|
||||||
self.debugging_opt(SHOW_SPAN)
|
self.debugging_opt(config::SHOW_SPAN)
|
||||||
}
|
}
|
||||||
pub fn sysroot<'a>(&'a self) -> &'a Path {
|
pub fn sysroot<'a>(&'a self) -> &'a Path {
|
||||||
match self.opts.maybe_sysroot {
|
match self.opts.maybe_sysroot {
|
||||||
|
@ -333,142 +188,63 @@ impl Session {
|
||||||
pub fn host_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
|
pub fn host_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
|
||||||
filesearch::FileSearch::new(
|
filesearch::FileSearch::new(
|
||||||
self.sysroot(),
|
self.sysroot(),
|
||||||
host_triple(),
|
driver::host_triple(),
|
||||||
&self.opts.addl_lib_search_paths)
|
&self.opts.addl_lib_search_paths)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Some reasonable defaults
|
pub fn build_session(sopts: config::Options,
|
||||||
pub fn basic_options() -> Options {
|
local_crate_source_file: Option<Path>)
|
||||||
Options {
|
-> Session {
|
||||||
crate_types: Vec::new(),
|
let codemap = codemap::CodeMap::new();
|
||||||
gc: false,
|
let diagnostic_handler =
|
||||||
optimize: No,
|
diagnostic::default_handler();
|
||||||
debuginfo: NoDebugInfo,
|
let span_diagnostic_handler =
|
||||||
lint_opts: Vec::new(),
|
diagnostic::mk_span_handler(diagnostic_handler, codemap);
|
||||||
output_types: Vec::new(),
|
|
||||||
addl_lib_search_paths: RefCell::new(HashSet::new()),
|
build_session_(sopts, local_crate_source_file, span_diagnostic_handler)
|
||||||
maybe_sysroot: None,
|
}
|
||||||
target_triple: host_triple().to_owned(),
|
|
||||||
cfg: Vec::new(),
|
pub fn build_session_(sopts: config::Options,
|
||||||
test: false,
|
local_crate_source_file: Option<Path>,
|
||||||
parse_only: false,
|
span_diagnostic: diagnostic::SpanHandler)
|
||||||
no_trans: false,
|
-> Session {
|
||||||
no_analysis: false,
|
let target_cfg = config::build_target_config(&sopts);
|
||||||
debugging_opts: 0,
|
let p_s = parse::new_parse_sess_special_handler(span_diagnostic);
|
||||||
write_dependency_info: (false, None),
|
let default_sysroot = match sopts.maybe_sysroot {
|
||||||
print_metas: (false, false, false),
|
Some(_) => None,
|
||||||
cg: basic_codegen_options(),
|
None => Some(filesearch::get_or_default_sysroot())
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make the path absolute, if necessary
|
||||||
|
let local_crate_source_file = local_crate_source_file.map(|path|
|
||||||
|
if path.is_absolute() {
|
||||||
|
path.clone()
|
||||||
|
} else {
|
||||||
|
os::getcwd().join(path.clone())
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Session {
|
||||||
|
targ_cfg: target_cfg,
|
||||||
|
opts: sopts,
|
||||||
|
cstore: CStore::new(token::get_ident_interner()),
|
||||||
|
parse_sess: p_s,
|
||||||
|
// For a library crate, this is always none
|
||||||
|
entry_fn: RefCell::new(None),
|
||||||
|
entry_type: Cell::new(None),
|
||||||
|
macro_registrar_fn: Cell::new(None),
|
||||||
|
default_sysroot: default_sysroot,
|
||||||
|
local_crate_source_file: local_crate_source_file,
|
||||||
|
working_dir: os::getcwd(),
|
||||||
|
lints: RefCell::new(NodeMap::new()),
|
||||||
|
node_id: Cell::new(1),
|
||||||
|
crate_types: RefCell::new(Vec::new()),
|
||||||
|
features: front::feature_gate::Features::new(),
|
||||||
|
recursion_limit: Cell::new(64),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Declare a macro that will define all CodegenOptions fields and parsers all
|
|
||||||
/// at once. The goal of this macro is to define an interface that can be
|
|
||||||
/// programmatically used by the option parser in order to initialize the struct
|
|
||||||
/// without hardcoding field names all over the place.
|
|
||||||
///
|
|
||||||
/// The goal is to invoke this macro once with the correct fields, and then this
|
|
||||||
/// macro generates all necessary code. The main gotcha of this macro is the
|
|
||||||
/// cgsetters module which is a bunch of generated code to parse an option into
|
|
||||||
/// its respective field in the struct. There are a few hand-written parsers for
|
|
||||||
/// parsing specific types of values in this module.
|
|
||||||
macro_rules! cgoptions(
|
|
||||||
($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
|
|
||||||
(
|
|
||||||
#[deriving(Clone)]
|
|
||||||
pub struct CodegenOptions { $(pub $opt: $t),* }
|
|
||||||
|
|
||||||
pub fn basic_codegen_options() -> CodegenOptions {
|
|
||||||
CodegenOptions { $($opt: $init),* }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool;
|
|
||||||
pub static CG_OPTIONS: &'static [(&'static str, CodegenSetter,
|
|
||||||
&'static str)] =
|
|
||||||
&[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ];
|
|
||||||
|
|
||||||
mod cgsetters {
|
|
||||||
use super::CodegenOptions;
|
|
||||||
|
|
||||||
$(
|
|
||||||
pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool {
|
|
||||||
$parse(&mut cg.$opt, v)
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
|
|
||||||
fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
|
|
||||||
match v {
|
|
||||||
Some(..) => false,
|
|
||||||
None => { *slot = true; true }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_opt_string(slot: &mut Option<~str>, v: Option<&str>) -> bool {
|
|
||||||
match v {
|
|
||||||
Some(s) => { *slot = Some(s.to_owned()); true },
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_string(slot: &mut ~str, v: Option<&str>) -> bool {
|
|
||||||
match v {
|
|
||||||
Some(s) => { *slot = s.to_owned(); true },
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_list(slot: &mut Vec<~str>, v: Option<&str>)
|
|
||||||
-> bool {
|
|
||||||
match v {
|
|
||||||
Some(s) => {
|
|
||||||
for s in s.words() {
|
|
||||||
slot.push(s.to_owned());
|
|
||||||
}
|
|
||||||
true
|
|
||||||
},
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
) )
|
|
||||||
|
|
||||||
cgoptions!(
|
|
||||||
ar: Option<~str> = (None, parse_opt_string,
|
|
||||||
"tool to assemble archives with"),
|
|
||||||
linker: Option<~str> = (None, parse_opt_string,
|
|
||||||
"system linker to link outputs with"),
|
|
||||||
link_args: Vec<~str> = (Vec::new(), parse_list,
|
|
||||||
"extra arguments to pass to the linker (space separated)"),
|
|
||||||
target_cpu: ~str = ("generic".to_owned(), parse_string,
|
|
||||||
"select target processor (llc -mcpu=help for details)"),
|
|
||||||
target_feature: ~str = ("".to_owned(), parse_string,
|
|
||||||
"target specific attributes (llc -mattr=help for details)"),
|
|
||||||
passes: Vec<~str> = (Vec::new(), parse_list,
|
|
||||||
"a list of extra LLVM passes to run (space separated)"),
|
|
||||||
llvm_args: Vec<~str> = (Vec::new(), parse_list,
|
|
||||||
"a list of arguments to pass to llvm (space separated)"),
|
|
||||||
save_temps: bool = (false, parse_bool,
|
|
||||||
"save all temporary output files during compilation"),
|
|
||||||
android_cross_path: Option<~str> = (None, parse_opt_string,
|
|
||||||
"the path to the Android NDK"),
|
|
||||||
no_rpath: bool = (false, parse_bool,
|
|
||||||
"disables setting the rpath in libs/exes"),
|
|
||||||
no_prepopulate_passes: bool = (false, parse_bool,
|
|
||||||
"don't pre-populate the pass manager with a list of passes"),
|
|
||||||
no_vectorize_loops: bool = (false, parse_bool,
|
|
||||||
"don't run the loop vectorization optimization passes"),
|
|
||||||
no_vectorize_slp: bool = (false, parse_bool,
|
|
||||||
"don't run LLVM's SLP vectorization pass"),
|
|
||||||
soft_float: bool = (false, parse_bool,
|
|
||||||
"generate software floating point library calls"),
|
|
||||||
prefer_dynamic: bool = (false, parse_bool,
|
|
||||||
"prefer dynamic linking to static linking"),
|
|
||||||
no_integrated_as: bool = (false, parse_bool,
|
|
||||||
"use an external assembler rather than LLVM's integrated one"),
|
|
||||||
relocation_model: ~str = ("pic".to_owned(), parse_string,
|
|
||||||
"choose the relocation model to use (llc -relocation-model for details)"),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Seems out of place, but it uses session, so I'm putting it here
|
// Seems out of place, but it uses session, so I'm putting it here
|
||||||
pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> StrBuf)
|
pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> StrBuf)
|
||||||
|
@ -476,72 +252,3 @@ pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> StrBuf)
|
||||||
diagnostic::expect(sess.diagnostic(), opt, msg)
|
diagnostic::expect(sess.diagnostic(), opt, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_lib_output() -> CrateType {
|
|
||||||
CrateTypeRlib
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn collect_crate_types(session: &Session,
|
|
||||||
attrs: &[ast::Attribute]) -> Vec<CrateType> {
|
|
||||||
// If we're generating a test executable, then ignore all other output
|
|
||||||
// styles at all other locations
|
|
||||||
if session.opts.test {
|
|
||||||
return vec!(CrateTypeExecutable)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only check command line flags if present. If no types are specified by
|
|
||||||
// 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 {
|
|
||||||
let iter = attrs.iter().filter_map(|a| {
|
|
||||||
if a.name().equiv(&("crate_type")) {
|
|
||||||
match a.value_str() {
|
|
||||||
Some(ref n) if n.equiv(&("rlib")) => Some(CrateTypeRlib),
|
|
||||||
Some(ref n) if n.equiv(&("dylib")) => Some(CrateTypeDylib),
|
|
||||||
Some(ref n) if n.equiv(&("lib")) => {
|
|
||||||
Some(default_lib_output())
|
|
||||||
}
|
|
||||||
Some(ref n) if n.equiv(&("staticlib")) => {
|
|
||||||
Some(CrateTypeStaticlib)
|
|
||||||
}
|
|
||||||
Some(ref n) if n.equiv(&("bin")) => Some(CrateTypeExecutable),
|
|
||||||
Some(_) => {
|
|
||||||
session.add_lint(lint::UnknownCrateType,
|
|
||||||
ast::CRATE_NODE_ID,
|
|
||||||
a.span,
|
|
||||||
"invalid `crate_type` value".to_owned());
|
|
||||||
None
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
session.add_lint(lint::UnknownCrateType, ast::CRATE_NODE_ID,
|
|
||||||
a.span, "`crate_type` requires a value".to_owned());
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
|
||||||
base.extend(iter);
|
|
||||||
if base.len() == 0 {
|
|
||||||
base.push(CrateTypeExecutable);
|
|
||||||
}
|
|
||||||
base.as_mut_slice().sort();
|
|
||||||
base.dedup();
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sess_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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use driver::session;
|
use driver::config;
|
||||||
use driver::session::Session;
|
use driver::session::Session;
|
||||||
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
@ -87,7 +87,7 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> {
|
||||||
});
|
});
|
||||||
|
|
||||||
let any_exe = self.sess.crate_types.borrow().iter().any(|ty| {
|
let any_exe = self.sess.crate_types.borrow().iter().any(|ty| {
|
||||||
*ty == session::CrateTypeExecutable
|
*ty == config::CrateTypeExecutable
|
||||||
});
|
});
|
||||||
if use_start(&krate) && any_exe {
|
if use_start(&krate) && any_exe {
|
||||||
vis.push(ast::ViewItem {
|
vis.push(ast::ViewItem {
|
||||||
|
|
|
@ -44,23 +44,6 @@ extern crate libc;
|
||||||
#[phase(syntax, link)]
|
#[phase(syntax, link)]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
use back::link;
|
|
||||||
use driver::session;
|
|
||||||
use middle::lint;
|
|
||||||
|
|
||||||
use d = driver::driver;
|
|
||||||
|
|
||||||
use std::any::AnyRefExt;
|
|
||||||
use std::cmp;
|
|
||||||
use std::io;
|
|
||||||
use std::os;
|
|
||||||
use std::str;
|
|
||||||
use std::task::TaskBuilder;
|
|
||||||
use syntax::ast;
|
|
||||||
use syntax::diagnostic::Emitter;
|
|
||||||
use syntax::diagnostic;
|
|
||||||
use syntax::parse;
|
|
||||||
|
|
||||||
pub mod middle {
|
pub mod middle {
|
||||||
pub mod trans;
|
pub mod trans;
|
||||||
pub mod ty;
|
pub mod ty;
|
||||||
|
@ -136,309 +119,8 @@ pub mod lib {
|
||||||
pub mod llvmdeps;
|
pub mod llvmdeps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BUG_REPORT_URL: &'static str =
|
|
||||||
"http://static.rust-lang.org/doc/master/complement-bugreport.html";
|
|
||||||
|
|
||||||
pub fn version(argv0: &str) {
|
|
||||||
let vers = match option_env!("CFG_VERSION") {
|
|
||||||
Some(vers) => vers,
|
|
||||||
None => "unknown version"
|
|
||||||
};
|
|
||||||
println!("{} {}", argv0, vers);
|
|
||||||
println!("host: {}", d::host_triple());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn usage(argv0: &str) {
|
|
||||||
let message = format!("Usage: {} [OPTIONS] INPUT", argv0);
|
|
||||||
println!("{}\n\
|
|
||||||
Additional help:
|
|
||||||
-C help Print codegen options
|
|
||||||
-W help Print 'lint' options and default settings
|
|
||||||
-Z help Print internal options for debugging rustc\n",
|
|
||||||
getopts::usage(message, d::optgroups().as_slice()));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn describe_warnings() {
|
|
||||||
println!("
|
|
||||||
Available lint options:
|
|
||||||
-W <foo> Warn about <foo>
|
|
||||||
-A <foo> Allow <foo>
|
|
||||||
-D <foo> Deny <foo>
|
|
||||||
-F <foo> Forbid <foo> (deny, and deny all overrides)
|
|
||||||
");
|
|
||||||
|
|
||||||
let lint_dict = lint::get_lint_dict();
|
|
||||||
let mut lint_dict = lint_dict.move_iter()
|
|
||||||
.map(|(k, v)| (v, k))
|
|
||||||
.collect::<Vec<(lint::LintSpec, &'static str)> >();
|
|
||||||
lint_dict.as_mut_slice().sort();
|
|
||||||
|
|
||||||
let mut max_key = 0;
|
|
||||||
for &(_, name) in lint_dict.iter() {
|
|
||||||
max_key = cmp::max(name.len(), max_key);
|
|
||||||
}
|
|
||||||
fn padded(max: uint, s: &str) -> ~str {
|
|
||||||
" ".repeat(max - s.len()) + s
|
|
||||||
}
|
|
||||||
println!("\nAvailable lint checks:\n");
|
|
||||||
println!(" {} {:7.7s} {}",
|
|
||||||
padded(max_key, "name"), "default", "meaning");
|
|
||||||
println!(" {} {:7.7s} {}\n",
|
|
||||||
padded(max_key, "----"), "-------", "-------");
|
|
||||||
for (spec, name) in lint_dict.move_iter() {
|
|
||||||
let name = name.replace("_", "-");
|
|
||||||
println!(" {} {:7.7s} {}",
|
|
||||||
padded(max_key, name),
|
|
||||||
lint::level_to_str(spec.default),
|
|
||||||
spec.desc);
|
|
||||||
}
|
|
||||||
println!("");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn describe_debug_flags() {
|
|
||||||
println!("\nAvailable debug options:\n");
|
|
||||||
let r = session::debugging_opts_map();
|
|
||||||
for tuple in r.iter() {
|
|
||||||
match *tuple {
|
|
||||||
(ref name, ref desc, _) => {
|
|
||||||
println!(" -Z {:>20s} -- {}", *name, *desc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn describe_codegen_flags() {
|
|
||||||
println!("\nAvailable codegen options:\n");
|
|
||||||
let mut cg = session::basic_codegen_options();
|
|
||||||
for &(name, parser, desc) in session::CG_OPTIONS.iter() {
|
|
||||||
// we invoke the parser function on `None` to see if this option needs
|
|
||||||
// an argument or not.
|
|
||||||
let (width, extra) = if parser(&mut cg, None) {
|
|
||||||
(25, "")
|
|
||||||
} else {
|
|
||||||
(21, "=val")
|
|
||||||
};
|
|
||||||
println!(" -C {:>width$s}{} -- {}", name.replace("_", "-"),
|
|
||||||
extra, desc, width=width);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run_compiler(args: &[~str]) {
|
|
||||||
let mut args = Vec::from_slice(args);
|
|
||||||
let binary = args.shift().unwrap();
|
|
||||||
|
|
||||||
if args.is_empty() { usage(binary); return; }
|
|
||||||
|
|
||||||
let matches =
|
|
||||||
&match getopts::getopts(args.as_slice(), d::optgroups().as_slice()) {
|
|
||||||
Ok(m) => m,
|
|
||||||
Err(f) => {
|
|
||||||
d::early_error(f.to_err_msg());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if matches.opt_present("h") || matches.opt_present("help") {
|
|
||||||
usage(binary);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let lint_flags = matches.opt_strs("W").move_iter().collect::<Vec<_>>().append(
|
|
||||||
matches.opt_strs("warn").as_slice());
|
|
||||||
if lint_flags.iter().any(|x| x == &"help".to_owned()) {
|
|
||||||
describe_warnings();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let r = matches.opt_strs("Z");
|
|
||||||
if r.iter().any(|x| x == &"help".to_owned()) {
|
|
||||||
describe_debug_flags();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cg_flags = matches.opt_strs("C");
|
|
||||||
if cg_flags.iter().any(|x| x == &"help".to_owned()) {
|
|
||||||
describe_codegen_flags();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if cg_flags.contains(&"passes=list".to_owned()) {
|
|
||||||
unsafe { lib::llvm::llvm::LLVMRustPrintPasses(); }
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if matches.opt_present("v") || matches.opt_present("version") {
|
|
||||||
version(binary);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let (input, input_file_path) = match matches.free.len() {
|
|
||||||
0u => d::early_error("no input filename given"),
|
|
||||||
1u => {
|
|
||||||
let ifile = matches.free.get(0).as_slice();
|
|
||||||
if ifile == "-" {
|
|
||||||
let contents = io::stdin().read_to_end().unwrap();
|
|
||||||
let src = str::from_utf8(contents.as_slice()).unwrap().to_owned();
|
|
||||||
(d::StrInput(src), None)
|
|
||||||
} else {
|
|
||||||
(d::FileInput(Path::new(ifile)), Some(Path::new(ifile)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => d::early_error("multiple input filenames provided")
|
|
||||||
};
|
|
||||||
|
|
||||||
let sopts = d::build_session_options(matches);
|
|
||||||
let sess = d::build_session(sopts, input_file_path);
|
|
||||||
let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
|
|
||||||
let ofile = matches.opt_str("o").map(|o| Path::new(o));
|
|
||||||
let cfg = d::build_configuration(&sess);
|
|
||||||
let pretty = matches.opt_default("pretty", "normal").map(|a| {
|
|
||||||
d::parse_pretty(&sess, a)
|
|
||||||
});
|
|
||||||
match pretty {
|
|
||||||
Some::<d::PpMode>(ppm) => {
|
|
||||||
d::pretty_print_input(sess, cfg, &input, ppm, ofile);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
None::<d::PpMode> => {/* continue */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.contains(&("ls".to_owned())) {
|
|
||||||
match input {
|
|
||||||
d::FileInput(ref ifile) => {
|
|
||||||
let mut stdout = io::stdout();
|
|
||||||
d::list_metadata(&sess, &(*ifile), &mut stdout).unwrap();
|
|
||||||
}
|
|
||||||
d::StrInput(_) => {
|
|
||||||
d::early_error("can not list metadata for stdin");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let (crate_id, crate_name, crate_file_name) = sess.opts.print_metas;
|
|
||||||
// these nasty nested conditions are to avoid doing extra work
|
|
||||||
if crate_id || crate_name || crate_file_name {
|
|
||||||
let attrs = parse_crate_attrs(&sess, &input);
|
|
||||||
let t_outputs = d::build_output_filenames(&input, &odir, &ofile,
|
|
||||||
attrs.as_slice(), &sess);
|
|
||||||
let id = link::find_crate_id(attrs.as_slice(), t_outputs.out_filestem);
|
|
||||||
|
|
||||||
if crate_id {
|
|
||||||
println!("{}", id.to_str());
|
|
||||||
}
|
|
||||||
if crate_name {
|
|
||||||
println!("{}", id.name);
|
|
||||||
}
|
|
||||||
if crate_file_name {
|
|
||||||
let crate_types = session::collect_crate_types(&sess,
|
|
||||||
attrs.as_slice());
|
|
||||||
for &style in crate_types.iter() {
|
|
||||||
let fname = link::filename_for_input(&sess, style, &id,
|
|
||||||
&t_outputs.with_extension(""));
|
|
||||||
println!("{}", fname.filename_display());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d::compile_input(sess, cfg, &input, &odir, &ofile);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_crate_attrs(sess: &session::Session, input: &d::Input) ->
|
|
||||||
Vec<ast::Attribute> {
|
|
||||||
let result = match *input {
|
|
||||||
d::FileInput(ref ifile) => {
|
|
||||||
parse::parse_crate_attrs_from_file(ifile,
|
|
||||||
Vec::new(),
|
|
||||||
&sess.parse_sess)
|
|
||||||
}
|
|
||||||
d::StrInput(ref src) => {
|
|
||||||
parse::parse_crate_attrs_from_source_str(
|
|
||||||
d::anon_src().to_strbuf(),
|
|
||||||
src.to_strbuf(),
|
|
||||||
Vec::new(),
|
|
||||||
&sess.parse_sess)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
result.move_iter().collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run a procedure which will detect failures in the compiler and print nicer
|
|
||||||
/// error messages rather than just failing the test.
|
|
||||||
///
|
|
||||||
/// The diagnostic emitter yielded to the procedure should be used for reporting
|
|
||||||
/// errors of the compiler.
|
|
||||||
pub fn monitor(f: proc():Send) {
|
|
||||||
// FIXME: This is a hack for newsched since it doesn't support split stacks.
|
|
||||||
// rustc needs a lot of stack! When optimizations are disabled, it needs
|
|
||||||
// even *more* stack than usual as well.
|
|
||||||
#[cfg(rtopt)]
|
|
||||||
static STACK_SIZE: uint = 6000000; // 6MB
|
|
||||||
#[cfg(not(rtopt))]
|
|
||||||
static STACK_SIZE: uint = 20000000; // 20MB
|
|
||||||
|
|
||||||
let mut task_builder = TaskBuilder::new().named("rustc");
|
|
||||||
|
|
||||||
// FIXME: Hacks on hacks. If the env is trying to override the stack size
|
|
||||||
// then *don't* set it explicitly.
|
|
||||||
if os::getenv("RUST_MIN_STACK").is_none() {
|
|
||||||
task_builder.opts.stack_size = Some(STACK_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
let (tx, rx) = channel();
|
|
||||||
let w = io::ChanWriter::new(tx);
|
|
||||||
let mut r = io::ChanReader::new(rx);
|
|
||||||
|
|
||||||
match task_builder.try(proc() {
|
|
||||||
io::stdio::set_stderr(box w);
|
|
||||||
f()
|
|
||||||
}) {
|
|
||||||
Ok(()) => { /* fallthrough */ }
|
|
||||||
Err(value) => {
|
|
||||||
// Task failed without emitting a fatal diagnostic
|
|
||||||
if !value.is::<diagnostic::FatalError>() {
|
|
||||||
let mut emitter = diagnostic::EmitterWriter::stderr();
|
|
||||||
|
|
||||||
// a .span_bug or .bug call has already printed what
|
|
||||||
// it wants to print.
|
|
||||||
if !value.is::<diagnostic::ExplicitBug>() {
|
|
||||||
emitter.emit(
|
|
||||||
None,
|
|
||||||
"unexpected failure",
|
|
||||||
diagnostic::Bug);
|
|
||||||
}
|
|
||||||
|
|
||||||
let xs = [
|
|
||||||
"the compiler hit an unexpected failure path. this is a bug.".to_owned(),
|
|
||||||
"we would appreciate a bug report: " + BUG_REPORT_URL,
|
|
||||||
"run with `RUST_BACKTRACE=1` for a backtrace".to_owned(),
|
|
||||||
];
|
|
||||||
for note in xs.iter() {
|
|
||||||
emitter.emit(None, *note, diagnostic::Note)
|
|
||||||
}
|
|
||||||
|
|
||||||
match r.read_to_str() {
|
|
||||||
Ok(s) => println!("{}", s),
|
|
||||||
Err(e) => emitter.emit(None,
|
|
||||||
format!("failed to read internal stderr: {}", e),
|
|
||||||
diagnostic::Error),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fail so the process returns a failure code, but don't pollute the
|
|
||||||
// output with some unnecessary failure messages, we've already
|
|
||||||
// printed everything that we needed to.
|
|
||||||
io::stdio::set_stderr(box io::util::NullWriter);
|
|
||||||
fail!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
std::os::set_exit_status(main_args(std::os::args().as_slice()));
|
std::os::set_exit_status(driver::main_args(std::os::args().as_slice()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_args(args: &[~str]) -> int {
|
|
||||||
let owned_args = args.to_owned();
|
|
||||||
monitor(proc() run_compiler(owned_args));
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
use back::link;
|
use back::link;
|
||||||
use back::svh::Svh;
|
use back::svh::Svh;
|
||||||
use driver::session::Session;
|
use driver::session::Session;
|
||||||
use driver::{driver, session};
|
use driver::{driver, config};
|
||||||
use metadata::cstore;
|
use metadata::cstore;
|
||||||
use metadata::cstore::CStore;
|
use metadata::cstore::CStore;
|
||||||
use metadata::decoder;
|
use metadata::decoder;
|
||||||
|
@ -331,7 +331,7 @@ fn resolve_crate<'a>(e: &mut Env,
|
||||||
id_hash: id_hash,
|
id_hash: id_hash,
|
||||||
hash: hash.map(|a| &*a),
|
hash: hash.map(|a| &*a),
|
||||||
filesearch: e.sess.target_filesearch(),
|
filesearch: e.sess.target_filesearch(),
|
||||||
os: session::sess_os_to_meta_os(e.sess.targ_cfg.os),
|
os: config::cfg_os_to_meta_os(e.sess.targ_cfg.os),
|
||||||
triple: e.sess.targ_cfg.target_strs.target_triple.as_slice(),
|
triple: e.sess.targ_cfg.target_strs.target_triple.as_slice(),
|
||||||
root: root,
|
root: root,
|
||||||
rejected_via_hash: vec!(),
|
rejected_via_hash: vec!(),
|
||||||
|
@ -387,7 +387,7 @@ impl<'a> CrateLoader for Loader<'a> {
|
||||||
let is_cross = target_triple != driver::host_triple();
|
let is_cross = target_triple != driver::host_triple();
|
||||||
let mut should_link = info.should_link && !is_cross;
|
let mut should_link = info.should_link && !is_cross;
|
||||||
let id_hash = link::crate_id_hash(&info.crate_id);
|
let id_hash = link::crate_id_hash(&info.crate_id);
|
||||||
let os = driver::get_os(driver::host_triple()).unwrap();
|
let os = config::get_os(driver::host_triple()).unwrap();
|
||||||
let mut load_ctxt = loader::Context {
|
let mut load_ctxt = loader::Context {
|
||||||
sess: self.env.sess,
|
sess: self.env.sess,
|
||||||
span: krate.span,
|
span: krate.span,
|
||||||
|
@ -397,7 +397,7 @@ impl<'a> CrateLoader for Loader<'a> {
|
||||||
hash: None,
|
hash: None,
|
||||||
filesearch: self.env.sess.host_filesearch(),
|
filesearch: self.env.sess.host_filesearch(),
|
||||||
triple: driver::host_triple(),
|
triple: driver::host_triple(),
|
||||||
os: session::sess_os_to_meta_os(os),
|
os: config::cfg_os_to_meta_os(os),
|
||||||
root: &None,
|
root: &None,
|
||||||
rejected_via_hash: vec!(),
|
rejected_via_hash: vec!(),
|
||||||
rejected_via_triple: vec!(),
|
rejected_via_triple: vec!(),
|
||||||
|
@ -408,7 +408,7 @@ impl<'a> CrateLoader for Loader<'a> {
|
||||||
// try loading from target crates (only valid if there are
|
// try loading from target crates (only valid if there are
|
||||||
// no syntax extensions)
|
// no syntax extensions)
|
||||||
load_ctxt.triple = target_triple;
|
load_ctxt.triple = target_triple;
|
||||||
load_ctxt.os = session::sess_os_to_meta_os(self.env.sess.targ_cfg.os);
|
load_ctxt.os = config::cfg_os_to_meta_os(self.env.sess.targ_cfg.os);
|
||||||
load_ctxt.filesearch = self.env.sess.target_filesearch();
|
load_ctxt.filesearch = self.env.sess.target_filesearch();
|
||||||
let lib = load_ctxt.load_library_crate();
|
let lib = load_ctxt.load_library_crate();
|
||||||
if decoder::get_macro_registrar_fn(lib.metadata.as_slice()).is_some() {
|
if decoder::get_macro_registrar_fn(lib.metadata.as_slice()).is_some() {
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
use back::svh::Svh;
|
use back::svh::Svh;
|
||||||
use driver::session;
|
use driver::config;
|
||||||
use metadata::common::*;
|
use metadata::common::*;
|
||||||
use metadata::cstore;
|
use metadata::cstore;
|
||||||
use metadata::decoder;
|
use metadata::decoder;
|
||||||
|
@ -1697,7 +1697,7 @@ fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
|
||||||
|
|
||||||
fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
|
fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
|
||||||
ebml_w.start_tag(tag_dylib_dependency_formats);
|
ebml_w.start_tag(tag_dylib_dependency_formats);
|
||||||
match ecx.tcx.dependency_formats.borrow().find(&session::CrateTypeDylib) {
|
match ecx.tcx.dependency_formats.borrow().find(&config::CrateTypeDylib) {
|
||||||
Some(arr) => {
|
Some(arr) => {
|
||||||
let s = arr.iter().enumerate().filter_map(|(i, slot)| {
|
let s = arr.iter().enumerate().filter_map(|(i, slot)| {
|
||||||
slot.map(|kind| format!("{}:{}", i + 1, match kind {
|
slot.map(|kind| format!("{}:{}", i + 1, match kind {
|
||||||
|
|
|
@ -65,6 +65,7 @@ use collections::HashMap;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
||||||
use driver::session;
|
use driver::session;
|
||||||
|
use driver::config;
|
||||||
use metadata::cstore;
|
use metadata::cstore;
|
||||||
use metadata::csearch;
|
use metadata::csearch;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
|
@ -80,7 +81,7 @@ pub type DependencyList = Vec<Option<cstore::LinkagePreference>>;
|
||||||
/// A mapping of all required dependencies for a particular flavor of output.
|
/// A mapping of all required dependencies for a particular flavor of output.
|
||||||
///
|
///
|
||||||
/// This is local to the tcx, and is generally relevant to one session.
|
/// This is local to the tcx, and is generally relevant to one session.
|
||||||
pub type Dependencies = HashMap<session::CrateType, DependencyList>;
|
pub type Dependencies = HashMap<config::CrateType, DependencyList>;
|
||||||
|
|
||||||
pub fn calculate(tcx: &ty::ctxt) {
|
pub fn calculate(tcx: &ty::ctxt) {
|
||||||
let mut fmts = tcx.dependency_formats.borrow_mut();
|
let mut fmts = tcx.dependency_formats.borrow_mut();
|
||||||
|
@ -91,11 +92,11 @@ pub fn calculate(tcx: &ty::ctxt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_type(sess: &session::Session,
|
fn calculate_type(sess: &session::Session,
|
||||||
ty: session::CrateType) -> DependencyList {
|
ty: config::CrateType) -> DependencyList {
|
||||||
match ty {
|
match ty {
|
||||||
// If the global prefer_dynamic switch is turned off, first attempt
|
// If the global prefer_dynamic switch is turned off, first attempt
|
||||||
// static linkage (this can fail).
|
// static linkage (this can fail).
|
||||||
session::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => {
|
config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => {
|
||||||
match attempt_static(sess) {
|
match attempt_static(sess) {
|
||||||
Some(v) => return v,
|
Some(v) => return v,
|
||||||
None => {}
|
None => {}
|
||||||
|
@ -104,11 +105,11 @@ fn calculate_type(sess: &session::Session,
|
||||||
|
|
||||||
// No linkage happens with rlibs, we just needed the metadata (which we
|
// No linkage happens with rlibs, we just needed the metadata (which we
|
||||||
// got long ago), so don't bother with anything.
|
// got long ago), so don't bother with anything.
|
||||||
session::CrateTypeRlib => return Vec::new(),
|
config::CrateTypeRlib => return Vec::new(),
|
||||||
|
|
||||||
// Staticlibs must have all static dependencies. If any fail to be
|
// Staticlibs must have all static dependencies. If any fail to be
|
||||||
// found, we generate some nice pretty errors.
|
// found, we generate some nice pretty errors.
|
||||||
session::CrateTypeStaticlib => {
|
config::CrateTypeStaticlib => {
|
||||||
match attempt_static(sess) {
|
match attempt_static(sess) {
|
||||||
Some(v) => return v,
|
Some(v) => return v,
|
||||||
None => {}
|
None => {}
|
||||||
|
@ -123,7 +124,7 @@ fn calculate_type(sess: &session::Session,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Everything else falls through below
|
// Everything else falls through below
|
||||||
session::CrateTypeExecutable | session::CrateTypeDylib => {},
|
config::CrateTypeExecutable | config::CrateTypeDylib => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut formats = HashMap::new();
|
let mut formats = HashMap::new();
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
|
||||||
use driver::session;
|
use driver::config;
|
||||||
use driver::session::Session;
|
use driver::session::Session;
|
||||||
use syntax::ast::{Crate, Name, NodeId, Item, ItemFn};
|
use syntax::ast::{Crate, Name, NodeId, Item, ItemFn};
|
||||||
use syntax::ast_map;
|
use syntax::ast_map;
|
||||||
|
@ -49,7 +49,7 @@ impl<'a> Visitor<()> for EntryContext<'a> {
|
||||||
|
|
||||||
pub fn find_entry_point(session: &Session, krate: &Crate, ast_map: &ast_map::Map) {
|
pub fn find_entry_point(session: &Session, krate: &Crate, ast_map: &ast_map::Map) {
|
||||||
let any_exe = session.crate_types.borrow().iter().any(|ty| {
|
let any_exe = session.crate_types.borrow().iter().any(|ty| {
|
||||||
*ty == session::CrateTypeExecutable
|
*ty == config::CrateTypeExecutable
|
||||||
});
|
});
|
||||||
if !any_exe {
|
if !any_exe {
|
||||||
// No need to find a main function
|
// No need to find a main function
|
||||||
|
@ -58,7 +58,7 @@ pub fn find_entry_point(session: &Session, krate: &Crate, ast_map: &ast_map::Map
|
||||||
|
|
||||||
// If the user wants no main function at all, then stop here.
|
// If the user wants no main function at all, then stop here.
|
||||||
if attr::contains_name(krate.attrs.as_slice(), "no_main") {
|
if attr::contains_name(krate.attrs.as_slice(), "no_main") {
|
||||||
session.entry_type.set(Some(session::EntryNone));
|
session.entry_type.set(Some(config::EntryNone));
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,13 +127,13 @@ fn find_item(item: &Item, ctxt: &mut EntryContext) {
|
||||||
fn configure_main(this: &mut EntryContext) {
|
fn configure_main(this: &mut EntryContext) {
|
||||||
if this.start_fn.is_some() {
|
if this.start_fn.is_some() {
|
||||||
*this.session.entry_fn.borrow_mut() = this.start_fn;
|
*this.session.entry_fn.borrow_mut() = this.start_fn;
|
||||||
this.session.entry_type.set(Some(session::EntryStart));
|
this.session.entry_type.set(Some(config::EntryStart));
|
||||||
} else if this.attr_main_fn.is_some() {
|
} else if this.attr_main_fn.is_some() {
|
||||||
*this.session.entry_fn.borrow_mut() = this.attr_main_fn;
|
*this.session.entry_fn.borrow_mut() = this.attr_main_fn;
|
||||||
this.session.entry_type.set(Some(session::EntryMain));
|
this.session.entry_type.set(Some(config::EntryMain));
|
||||||
} else if this.main_fn.is_some() {
|
} else if this.main_fn.is_some() {
|
||||||
*this.session.entry_fn.borrow_mut() = this.main_fn;
|
*this.session.entry_fn.borrow_mut() = this.main_fn;
|
||||||
this.session.entry_type.set(Some(session::EntryMain));
|
this.session.entry_type.set(Some(config::EntryMain));
|
||||||
} else {
|
} else {
|
||||||
// No main function
|
// No main function
|
||||||
this.session.err("main function not found");
|
this.session.err("main function not found");
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
// makes all other generics or inline functions that it references
|
// makes all other generics or inline functions that it references
|
||||||
// reachable as well.
|
// reachable as well.
|
||||||
|
|
||||||
use driver::session;
|
use driver::config;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use middle::typeck;
|
use middle::typeck;
|
||||||
use middle::privacy;
|
use middle::privacy;
|
||||||
|
@ -162,7 +162,7 @@ impl<'a> ReachableContext<'a> {
|
||||||
// Creates a new reachability computation context.
|
// Creates a new reachability computation context.
|
||||||
fn new(tcx: &'a ty::ctxt) -> ReachableContext<'a> {
|
fn new(tcx: &'a ty::ctxt) -> ReachableContext<'a> {
|
||||||
let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| {
|
let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| {
|
||||||
*ty != session::CrateTypeExecutable
|
*ty != config::CrateTypeExecutable
|
||||||
});
|
});
|
||||||
ReachableContext {
|
ReachableContext {
|
||||||
tcx: tcx,
|
tcx: tcx,
|
||||||
|
|
|
@ -195,7 +195,7 @@
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
use back::abi;
|
use back::abi;
|
||||||
use driver::session::FullDebugInfo;
|
use driver::config::FullDebugInfo;
|
||||||
use lib::llvm::{llvm, ValueRef, BasicBlockRef};
|
use lib::llvm::{llvm, ValueRef, BasicBlockRef};
|
||||||
use middle::const_eval;
|
use middle::const_eval;
|
||||||
use middle::lang_items::{UniqStrEqFnLangItem, StrEqFnLangItem};
|
use middle::lang_items::{UniqStrEqFnLangItem, StrEqFnLangItem};
|
||||||
|
|
|
@ -27,8 +27,9 @@
|
||||||
|
|
||||||
use back::link::{mangle_exported_name};
|
use back::link::{mangle_exported_name};
|
||||||
use back::{link, abi};
|
use back::{link, abi};
|
||||||
use driver::session;
|
use driver::config;
|
||||||
use driver::session::{Session, NoDebugInfo, FullDebugInfo};
|
use driver::config::{NoDebugInfo, FullDebugInfo};
|
||||||
|
use driver::session::Session;
|
||||||
use driver::driver::OutputFilenames;
|
use driver::driver::OutputFilenames;
|
||||||
use driver::driver::{CrateAnalysis, CrateTranslation};
|
use driver::driver::{CrateAnalysis, CrateTranslation};
|
||||||
use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
|
use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
|
||||||
|
@ -1725,11 +1726,11 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
|
||||||
main_llfn: ValueRef) {
|
main_llfn: ValueRef) {
|
||||||
let et = ccx.sess().entry_type.get().unwrap();
|
let et = ccx.sess().entry_type.get().unwrap();
|
||||||
match et {
|
match et {
|
||||||
session::EntryMain => {
|
config::EntryMain => {
|
||||||
create_entry_fn(ccx, main_llfn, true);
|
create_entry_fn(ccx, main_llfn, true);
|
||||||
}
|
}
|
||||||
session::EntryStart => create_entry_fn(ccx, main_llfn, false),
|
config::EntryStart => create_entry_fn(ccx, main_llfn, false),
|
||||||
session::EntryNone => {} // Do nothing.
|
config::EntryNone => {} // Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_entry_fn(ccx: &CrateContext,
|
fn create_entry_fn(ccx: &CrateContext,
|
||||||
|
@ -2068,7 +2069,7 @@ pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec<u8> {
|
||||||
use flate;
|
use flate;
|
||||||
|
|
||||||
let any_library = cx.sess().crate_types.borrow().iter().any(|ty| {
|
let any_library = cx.sess().crate_types.borrow().iter().any(|ty| {
|
||||||
*ty != session::CrateTypeExecutable
|
*ty != config::CrateTypeExecutable
|
||||||
});
|
});
|
||||||
if !any_library {
|
if !any_library {
|
||||||
return Vec::new()
|
return Vec::new()
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
use back::abi;
|
use back::abi;
|
||||||
use back::link::mangle_internal_name_by_path_and_seq;
|
use back::link::mangle_internal_name_by_path_and_seq;
|
||||||
use driver::session::FullDebugInfo;
|
use driver::config::FullDebugInfo;
|
||||||
use lib::llvm::ValueRef;
|
use lib::llvm::ValueRef;
|
||||||
use middle::freevars;
|
use middle::freevars;
|
||||||
use middle::lang_items::ClosureExchangeMallocFnLangItem;
|
use middle::lang_items::ClosureExchangeMallocFnLangItem;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
|
||||||
use driver::session::NoDebugInfo;
|
use driver::config::NoDebugInfo;
|
||||||
use driver::session::Session;
|
use driver::session::Session;
|
||||||
use lib::llvm::{ContextRef, ModuleRef, ValueRef};
|
use lib::llvm::{ContextRef, ModuleRef, ValueRef};
|
||||||
use lib::llvm::{llvm, TargetData, TypeNames};
|
use lib::llvm::{llvm, TargetData, TypeNames};
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use lib::llvm::*;
|
use lib::llvm::*;
|
||||||
use driver::session::FullDebugInfo;
|
use driver::config::FullDebugInfo;
|
||||||
use middle::lang_items::{FailFnLangItem, FailBoundsCheckFnLangItem};
|
use middle::lang_items::{FailFnLangItem, FailBoundsCheckFnLangItem};
|
||||||
use middle::trans::base::*;
|
use middle::trans::base::*;
|
||||||
use middle::trans::build::*;
|
use middle::trans::build::*;
|
||||||
|
|
|
@ -125,8 +125,8 @@ is still disabled, so there is no need to do anything special with source locati
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
use driver::session;
|
use driver::config;
|
||||||
use driver::session::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
use driver::config::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
||||||
use lib::llvm::llvm;
|
use lib::llvm::llvm;
|
||||||
use lib::llvm::{ModuleRef, ContextRef, ValueRef};
|
use lib::llvm::{ModuleRef, ContextRef, ValueRef};
|
||||||
use lib::llvm::debuginfo::*;
|
use lib::llvm::debuginfo::*;
|
||||||
|
@ -748,7 +748,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
|
||||||
true,
|
true,
|
||||||
scope_line as c_uint,
|
scope_line as c_uint,
|
||||||
FlagPrototyped as c_uint,
|
FlagPrototyped as c_uint,
|
||||||
cx.sess().opts.optimize != session::No,
|
cx.sess().opts.optimize != config::No,
|
||||||
llfn,
|
llfn,
|
||||||
template_parameters,
|
template_parameters,
|
||||||
ptr::null())
|
ptr::null())
|
||||||
|
@ -981,7 +981,7 @@ fn compile_unit_metadata(cx: &CrateContext) {
|
||||||
compile_unit_name,
|
compile_unit_name,
|
||||||
work_dir,
|
work_dir,
|
||||||
producer,
|
producer,
|
||||||
cx.sess().opts.optimize != session::No,
|
cx.sess().opts.optimize != config::No,
|
||||||
flags,
|
flags,
|
||||||
0,
|
0,
|
||||||
split_name);
|
split_name);
|
||||||
|
@ -1032,7 +1032,7 @@ fn declare_local(bcx: &Block,
|
||||||
file_metadata,
|
file_metadata,
|
||||||
loc.line as c_uint,
|
loc.line as c_uint,
|
||||||
type_metadata,
|
type_metadata,
|
||||||
cx.sess().opts.optimize != session::No,
|
cx.sess().opts.optimize != config::No,
|
||||||
0,
|
0,
|
||||||
argument_index)
|
argument_index)
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ independently:
|
||||||
|
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
use driver::session;
|
use driver::config;
|
||||||
|
|
||||||
use middle::resolve;
|
use middle::resolve;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
|
@ -414,9 +414,9 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
|
||||||
let tcx = ccx.tcx;
|
let tcx = ccx.tcx;
|
||||||
match *tcx.sess.entry_fn.borrow() {
|
match *tcx.sess.entry_fn.borrow() {
|
||||||
Some((id, sp)) => match tcx.sess.entry_type.get() {
|
Some((id, sp)) => match tcx.sess.entry_type.get() {
|
||||||
Some(session::EntryMain) => check_main_fn_ty(ccx, id, sp),
|
Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp),
|
||||||
Some(session::EntryStart) => check_start_fn_ty(ccx, id, sp),
|
Some(config::EntryStart) => check_start_fn_ty(ccx, id, sp),
|
||||||
Some(session::EntryNone) => {}
|
Some(config::EntryNone) => {}
|
||||||
None => tcx.sess.bug("entry function without a type")
|
None => tcx.sess.bug("entry function without a type")
|
||||||
},
|
},
|
||||||
None => {}
|
None => {}
|
||||||
|
|
|
@ -60,19 +60,20 @@ pub struct CrateAnalysis {
|
||||||
fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<~str>)
|
fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<~str>)
|
||||||
-> (DocContext, CrateAnalysis) {
|
-> (DocContext, CrateAnalysis) {
|
||||||
use syntax::codemap::dummy_spanned;
|
use syntax::codemap::dummy_spanned;
|
||||||
use rustc::driver::driver::{FileInput, build_configuration,
|
use rustc::driver::driver::{FileInput,
|
||||||
phase_1_parse_input,
|
phase_1_parse_input,
|
||||||
phase_2_configure_and_expand,
|
phase_2_configure_and_expand,
|
||||||
phase_3_run_analysis_passes};
|
phase_3_run_analysis_passes};
|
||||||
|
use rustc::driver::config::build_configuration;
|
||||||
|
|
||||||
let input = FileInput(cpath.clone());
|
let input = FileInput(cpath.clone());
|
||||||
|
|
||||||
let sessopts = driver::session::Options {
|
let sessopts = driver::config::Options {
|
||||||
maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
|
maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
|
||||||
addl_lib_search_paths: RefCell::new(libs),
|
addl_lib_search_paths: RefCell::new(libs),
|
||||||
crate_types: vec!(driver::session::CrateTypeDylib),
|
crate_types: vec!(driver::config::CrateTypeDylib),
|
||||||
lint_opts: vec!((lint::Warnings, lint::allow)),
|
lint_opts: vec!((lint::Warnings, lint::allow)),
|
||||||
..rustc::driver::session::basic_options().clone()
|
..rustc::driver::config::basic_options().clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,9 +82,9 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<~str>)
|
||||||
let span_diagnostic_handler =
|
let span_diagnostic_handler =
|
||||||
syntax::diagnostic::mk_span_handler(diagnostic_handler, codemap);
|
syntax::diagnostic::mk_span_handler(diagnostic_handler, codemap);
|
||||||
|
|
||||||
let sess = driver::driver::build_session_(sessopts,
|
let sess = driver::session::build_session_(sessopts,
|
||||||
Some(cpath.clone()),
|
Some(cpath.clone()),
|
||||||
span_diagnostic_handler);
|
span_diagnostic_handler);
|
||||||
|
|
||||||
let mut cfg = build_configuration(&sess);
|
let mut cfg = build_configuration(&sess);
|
||||||
for cfg_ in cfgs.move_iter() {
|
for cfg_ in cfgs.move_iter() {
|
||||||
|
|
|
@ -145,7 +145,7 @@ pub fn main_args(args: &[~str]) -> int {
|
||||||
usage(args[0]);
|
usage(args[0]);
|
||||||
return 0;
|
return 0;
|
||||||
} else if matches.opt_present("version") {
|
} else if matches.opt_present("version") {
|
||||||
rustc::version(args[0]);
|
rustc::driver::version(args[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ use std::strbuf::StrBuf;
|
||||||
use collections::{HashSet, HashMap};
|
use collections::{HashSet, HashMap};
|
||||||
use testing;
|
use testing;
|
||||||
use rustc::back::link;
|
use rustc::back::link;
|
||||||
|
use rustc::driver::config;
|
||||||
use rustc::driver::driver;
|
use rustc::driver::driver;
|
||||||
use rustc::driver::session;
|
use rustc::driver::session;
|
||||||
use rustc::metadata::creader::Loader;
|
use rustc::metadata::creader::Loader;
|
||||||
|
@ -43,11 +44,11 @@ pub fn run(input: &str,
|
||||||
let input_path = Path::new(input);
|
let input_path = Path::new(input);
|
||||||
let input = driver::FileInput(input_path.clone());
|
let input = driver::FileInput(input_path.clone());
|
||||||
|
|
||||||
let sessopts = session::Options {
|
let sessopts = config::Options {
|
||||||
maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
|
maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
|
||||||
addl_lib_search_paths: RefCell::new(libs.clone()),
|
addl_lib_search_paths: RefCell::new(libs.clone()),
|
||||||
crate_types: vec!(session::CrateTypeDylib),
|
crate_types: vec!(config::CrateTypeDylib),
|
||||||
..session::basic_options().clone()
|
..config::basic_options().clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,11 +57,11 @@ pub fn run(input: &str,
|
||||||
let span_diagnostic_handler =
|
let span_diagnostic_handler =
|
||||||
diagnostic::mk_span_handler(diagnostic_handler, codemap);
|
diagnostic::mk_span_handler(diagnostic_handler, codemap);
|
||||||
|
|
||||||
let sess = driver::build_session_(sessopts,
|
let sess = session::build_session_(sessopts,
|
||||||
Some(input_path.clone()),
|
Some(input_path.clone()),
|
||||||
span_diagnostic_handler);
|
span_diagnostic_handler);
|
||||||
|
|
||||||
let mut cfg = driver::build_configuration(&sess);
|
let mut cfg = config::build_configuration(&sess);
|
||||||
cfg.extend(cfgs.move_iter().map(|cfg_| {
|
cfg.extend(cfgs.move_iter().map(|cfg_| {
|
||||||
let cfg_ = token::intern_and_get_ident(cfg_);
|
let cfg_ = token::intern_and_get_ident(cfg_);
|
||||||
@dummy_spanned(ast::MetaWord(cfg_))
|
@dummy_spanned(ast::MetaWord(cfg_))
|
||||||
|
@ -101,17 +102,17 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
|
||||||
let test = maketest(test, cratename, loose_feature_gating);
|
let test = maketest(test, cratename, loose_feature_gating);
|
||||||
let input = driver::StrInput(test);
|
let input = driver::StrInput(test);
|
||||||
|
|
||||||
let sessopts = session::Options {
|
let sessopts = config::Options {
|
||||||
maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
|
maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
|
||||||
addl_lib_search_paths: RefCell::new(libs),
|
addl_lib_search_paths: RefCell::new(libs),
|
||||||
crate_types: vec!(session::CrateTypeExecutable),
|
crate_types: vec!(config::CrateTypeExecutable),
|
||||||
output_types: vec!(link::OutputTypeExe),
|
output_types: vec!(link::OutputTypeExe),
|
||||||
no_trans: no_run,
|
no_trans: no_run,
|
||||||
cg: session::CodegenOptions {
|
cg: config::CodegenOptions {
|
||||||
prefer_dynamic: true,
|
prefer_dynamic: true,
|
||||||
.. session::basic_codegen_options()
|
.. config::basic_codegen_options()
|
||||||
},
|
},
|
||||||
..session::basic_options().clone()
|
..config::basic_options().clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Shuffle around a few input and output handles here. We're going to pass
|
// Shuffle around a few input and output handles here. We're going to pass
|
||||||
|
@ -142,13 +143,13 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
|
||||||
let span_diagnostic_handler =
|
let span_diagnostic_handler =
|
||||||
diagnostic::mk_span_handler(diagnostic_handler, codemap);
|
diagnostic::mk_span_handler(diagnostic_handler, codemap);
|
||||||
|
|
||||||
let sess = driver::build_session_(sessopts,
|
let sess = session::build_session_(sessopts,
|
||||||
None,
|
None,
|
||||||
span_diagnostic_handler);
|
span_diagnostic_handler);
|
||||||
|
|
||||||
let outdir = TempDir::new("rustdoctest").expect("rustdoc needs a tempdir");
|
let outdir = TempDir::new("rustdoctest").expect("rustdoc needs a tempdir");
|
||||||
let out = Some(outdir.path().clone());
|
let out = Some(outdir.path().clone());
|
||||||
let cfg = driver::build_configuration(&sess);
|
let cfg = config::build_configuration(&sess);
|
||||||
driver::compile_input(sess, cfg, &input, &out, &None);
|
driver::compile_input(sess, cfg, &input, &out, &None);
|
||||||
|
|
||||||
if no_run { return }
|
if no_run { return }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue