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
src
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
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 syntax::abi;
|
||||
|
||||
@ -22,7 +22,7 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::
|
||||
return target_strs::t {
|
||||
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 {
|
||||
abi::OsMacos => {
|
||||
|
@ -12,8 +12,9 @@ use back::archive::{Archive, METADATA_FILENAME};
|
||||
use back::rpath;
|
||||
use back::svh::Svh;
|
||||
use driver::driver::{CrateTranslation, OutputFilenames};
|
||||
use driver::session::{NoDebugInfo, Session};
|
||||
use driver::session;
|
||||
use driver::config::NoDebugInfo;
|
||||
use driver::session::Session;
|
||||
use driver::config;
|
||||
use lib::llvm::llvm;
|
||||
use lib::llvm::ModuleRef;
|
||||
use lib;
|
||||
@ -92,8 +93,9 @@ pub mod write {
|
||||
use back::link::{OutputTypeExe, OutputTypeLlvmAssembly};
|
||||
use back::link::{OutputTypeObject};
|
||||
use driver::driver::{CrateTranslation, OutputFilenames};
|
||||
use driver::session::{NoDebugInfo, Session};
|
||||
use driver::session;
|
||||
use driver::config::NoDebugInfo;
|
||||
use driver::session::Session;
|
||||
use driver::config;
|
||||
use lib::llvm::llvm;
|
||||
use lib::llvm::{ModuleRef, TargetMachineRef, PassManagerRef};
|
||||
use lib;
|
||||
@ -139,10 +141,10 @@ pub mod write {
|
||||
}
|
||||
|
||||
let opt_level = match sess.opts.optimize {
|
||||
session::No => lib::llvm::CodeGenLevelNone,
|
||||
session::Less => lib::llvm::CodeGenLevelLess,
|
||||
session::Default => lib::llvm::CodeGenLevelDefault,
|
||||
session::Aggressive => lib::llvm::CodeGenLevelAggressive,
|
||||
config::No => lib::llvm::CodeGenLevelNone,
|
||||
config::Less => lib::llvm::CodeGenLevelLess,
|
||||
config::Default => lib::llvm::CodeGenLevelDefault,
|
||||
config::Aggressive => lib::llvm::CodeGenLevelAggressive,
|
||||
};
|
||||
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
|
||||
// inserted into the archive in order to allow LTO against it.
|
||||
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)) {
|
||||
output.temp_path(OutputTypeBitcode).with_c_str(|buf| {
|
||||
llvm::LLVMWriteBitcodeToFile(llmod, buf);
|
||||
@ -378,10 +380,10 @@ pub mod write {
|
||||
// Copy what clang does by turning on loop vectorization at O2 and
|
||||
// slp vectorization at O3
|
||||
let vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
|
||||
(sess.opts.optimize == session::Default ||
|
||||
sess.opts.optimize == session::Aggressive);
|
||||
(sess.opts.optimize == config::Default ||
|
||||
sess.opts.optimize == config::Aggressive);
|
||||
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_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 {
|
||||
let libname = output_lib_filename(id);
|
||||
match crate_type {
|
||||
session::CrateTypeRlib => {
|
||||
config::CrateTypeRlib => {
|
||||
out_filename.with_filename(format!("lib{}.rlib", libname))
|
||||
}
|
||||
session::CrateTypeDylib => {
|
||||
config::CrateTypeDylib => {
|
||||
let (prefix, suffix) = match sess.targ_cfg.os {
|
||||
abi::OsWin32 => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX),
|
||||
abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX),
|
||||
@ -840,16 +842,16 @@ pub fn filename_for_input(sess: &Session, crate_type: session::CrateType,
|
||||
};
|
||||
out_filename.with_filename(format!("{}{}{}", prefix, libname, suffix))
|
||||
}
|
||||
session::CrateTypeStaticlib => {
|
||||
config::CrateTypeStaticlib => {
|
||||
out_filename.with_filename(format!("lib{}.a", libname))
|
||||
}
|
||||
session::CrateTypeExecutable => out_filename.clone(),
|
||||
config::CrateTypeExecutable => out_filename.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn link_binary_output(sess: &Session,
|
||||
trans: &CrateTranslation,
|
||||
crate_type: session::CrateType,
|
||||
crate_type: config::CrateType,
|
||||
outputs: &OutputFilenames,
|
||||
id: &CrateId) -> Path {
|
||||
let obj_filename = outputs.temp_path(OutputTypeObject);
|
||||
@ -877,16 +879,16 @@ fn link_binary_output(sess: &Session,
|
||||
}
|
||||
|
||||
match crate_type {
|
||||
session::CrateTypeRlib => {
|
||||
config::CrateTypeRlib => {
|
||||
link_rlib(sess, Some(trans), &obj_filename, &out_filename);
|
||||
}
|
||||
session::CrateTypeStaticlib => {
|
||||
config::CrateTypeStaticlib => {
|
||||
link_staticlib(sess, &obj_filename, &out_filename);
|
||||
}
|
||||
session::CrateTypeExecutable => {
|
||||
config::CrateTypeExecutable => {
|
||||
link_natively(sess, trans, false, &obj_filename, &out_filename);
|
||||
}
|
||||
session::CrateTypeDylib => {
|
||||
config::CrateTypeDylib => {
|
||||
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();
|
||||
cc_args.push_all_move(link_args(sess, dylib, tmpdir.path(), trans,
|
||||
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("' '"));
|
||||
}
|
||||
|
||||
@ -1161,8 +1163,8 @@ fn link_args(sess: &Session,
|
||||
|
||||
// GNU-style linkers support optimization with -O. GNU ld doesn't need a
|
||||
// numeric argument, but other linkers do.
|
||||
if sess.opts.optimize == session::Default ||
|
||||
sess.opts.optimize == session::Aggressive {
|
||||
if sess.opts.optimize == config::Default ||
|
||||
sess.opts.optimize == config::Aggressive {
|
||||
args.push("-Wl,-O1".to_owned());
|
||||
}
|
||||
} 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.
|
||||
|
||||
let data = if dylib {
|
||||
trans.crate_formats.get(&session::CrateTypeDylib)
|
||||
trans.crate_formats.get(&config::CrateTypeDylib)
|
||||
} 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
|
||||
@ -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
|
||||
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 {
|
||||
stem.slice(3, stem.len()).to_owned()
|
||||
} else {
|
||||
|
@ -11,6 +11,7 @@
|
||||
use back::archive::ArchiveRO;
|
||||
use back::link;
|
||||
use driver::session;
|
||||
use driver::config;
|
||||
use lib::llvm::{ModuleRef, TargetMachineRef, llvm, True, False};
|
||||
use metadata::cstore;
|
||||
use util::common::time;
|
||||
@ -29,7 +30,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
|
||||
// Make sure we actually can run LTO
|
||||
for crate_type in sess.crate_types.borrow().iter() {
|
||||
match *crate_type {
|
||||
session::CrateTypeExecutable | session::CrateTypeStaticlib => {}
|
||||
config::CrateTypeExecutable | config::CrateTypeStaticlib => {}
|
||||
_ => {
|
||||
sess.fatal("lto can only be run for executables and \
|
||||
static library outputs");
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
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 syntax::abi;
|
||||
|
||||
@ -17,7 +17,7 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::
|
||||
return target_strs::t {
|
||||
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 {
|
||||
abi::OsMacos => {
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
|
||||
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 syntax::abi;
|
||||
|
||||
@ -18,7 +18,7 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::
|
||||
return target_strs::t {
|
||||
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 {
|
||||
abi::OsMacos => {
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
|
||||
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 syntax::abi;
|
||||
|
||||
@ -18,7 +18,7 @@ pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::
|
||||
return target_strs::t {
|
||||
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 {
|
||||
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::{arm, x86, x86_64, mips};
|
||||
use driver::session::{Aggressive, CrateTypeExecutable, CrateType,
|
||||
FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
||||
use driver::session::{Session, No, Less, Default};
|
||||
use driver::session;
|
||||
use driver::session::Session;
|
||||
use driver::config;
|
||||
use front;
|
||||
use lib::llvm::llvm;
|
||||
use lib::llvm::{ContextRef, ModuleRef};
|
||||
use metadata::common::LinkMeta;
|
||||
use metadata::{creader, filesearch};
|
||||
use metadata::cstore::CStore;
|
||||
use metadata::creader;
|
||||
use metadata::creader::Loader;
|
||||
use metadata;
|
||||
use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
|
||||
use middle::dependency_format;
|
||||
use middle;
|
||||
use util::common::time;
|
||||
use util::ppaux;
|
||||
use util::nodemap::{NodeMap, NodeSet};
|
||||
use util::nodemap::{NodeSet};
|
||||
|
||||
use serialize::{json, Encodable};
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::io;
|
||||
use std::io::fs;
|
||||
use std::io::MemReader;
|
||||
use std::os;
|
||||
use getopts::{optopt, optmulti, optflag, optflagopt};
|
||||
use getopts;
|
||||
use syntax::ast;
|
||||
use syntax::abi;
|
||||
use syntax::attr;
|
||||
use syntax::attr::{AttrMetaMethods};
|
||||
use syntax::codemap;
|
||||
use syntax::crateid::CrateId;
|
||||
use syntax::diagnostic;
|
||||
use syntax::diagnostic::Emitter;
|
||||
use syntax::ext::base::CrateLoader;
|
||||
use syntax::parse;
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax::parse::token;
|
||||
use syntax::print::{pp, pprust};
|
||||
use syntax;
|
||||
|
||||
pub enum PpMode {
|
||||
PpmNormal,
|
||||
PpmExpanded,
|
||||
PpmTyped,
|
||||
PpmIdentified,
|
||||
PpmExpandedIdentified
|
||||
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 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 {
|
||||
/// Load source from file
|
||||
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 json = json::PrettyEncoder::new(&mut stdout);
|
||||
// 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) {
|
||||
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", (), |_|
|
||||
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|
|
||||
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 json = json::PrettyEncoder::new(&mut stdout);
|
||||
// unwrapping so IoError isn't ignored
|
||||
@ -466,7 +427,7 @@ pub fn stop_after_phase_1(sess: &Session) -> bool {
|
||||
if sess.show_span() {
|
||||
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 {
|
||||
@ -474,7 +435,7 @@ pub fn stop_after_phase_2(sess: &Session) -> bool {
|
||||
debug!("invoked with --no-analysis, returning early from compile_input");
|
||||
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 {
|
||||
@ -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;
|
||||
|
||||
impl pprust::PpAnn for IdentifiedAnnotation {
|
||||
@ -657,7 +578,7 @@ impl pprust::PpAnn for TypedAnnotation {
|
||||
pub fn pretty_print_input(sess: Session,
|
||||
cfg: ast::CrateConfig,
|
||||
input: &Input,
|
||||
ppm: PpMode,
|
||||
ppm: ::driver::PpMode,
|
||||
ofile: Option<Path>) {
|
||||
let krate = phase_1_parse_input(&sess, cfg, input);
|
||||
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> {
|
||||
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: &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)
|
||||
}
|
||||
pub fn collect_crate_types(session: &Session,
|
||||
attrs: &[ast::Attribute]) -> Vec<config::CrateType> {
|
||||
// If we're generating a test executable, then ignore all other output
|
||||
// styles at all other locations
|
||||
if session.opts.test {
|
||||
return vec!(config::CrateTypeExecutable)
|
||||
}
|
||||
|
||||
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 = 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));
|
||||
}
|
||||
}
|
||||
// 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 {
|
||||
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);
|
||||
|
||||
session::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,
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
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(config::CrateTypeRlib),
|
||||
Some(ref n) if n.equiv(&("dylib")) => Some(config::CrateTypeDylib),
|
||||
Some(ref n) if n.equiv(&("lib")) => {
|
||||
Some(config::default_lib_output())
|
||||
}
|
||||
Some(ref n) if n.equiv(&("staticlib")) => {
|
||||
Some(config::CrateTypeStaticlib)
|
||||
}
|
||||
Some(ref n) if n.equiv(&("bin")) => Some(config::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
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if !found {
|
||||
early_error(format!("unknown codegen option: `{}`", key));
|
||||
});
|
||||
base.extend(iter);
|
||||
if base.len() == 0 {
|
||||
base.push(config::CrateTypeExecutable);
|
||||
}
|
||||
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 {
|
||||
@ -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;
|
||||
|
||||
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 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.
|
||||
|
||||
|
||||
use back::target_strs;
|
||||
use back;
|
||||
use driver::driver::host_triple;
|
||||
use driver::config;
|
||||
use driver::driver;
|
||||
use front;
|
||||
use metadata::cstore::CStore;
|
||||
use metadata::filesearch;
|
||||
use metadata;
|
||||
use middle::lint;
|
||||
use util::nodemap::NodeMap;
|
||||
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::ast::NodeId;
|
||||
use syntax::ast::{IntTy, UintTy};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::diagnostic;
|
||||
use syntax::parse;
|
||||
use syntax::parse::token;
|
||||
use syntax::parse::ParseSess;
|
||||
use syntax::{abi, ast, codemap};
|
||||
use syntax::{ast, codemap};
|
||||
|
||||
use std::os;
|
||||
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 targ_cfg: Config,
|
||||
pub opts: Options,
|
||||
pub cstore: metadata::cstore::CStore,
|
||||
pub targ_cfg: config::Config,
|
||||
pub opts: config::Options,
|
||||
pub cstore: CStore,
|
||||
pub parse_sess: ParseSess,
|
||||
// For a library crate, this is always none
|
||||
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 default_sysroot: Option<Path>,
|
||||
// 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 lints: RefCell<NodeMap<Vec<(lint::Lint, codemap::Span, ~str)>>>,
|
||||
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,
|
||||
|
||||
/// The maximum recursion limit for potentially infinitely recursive
|
||||
@ -289,33 +144,33 @@ impl Session {
|
||||
pub fn impossible_case(&self, sp: Span, msg: &str) -> ! {
|
||||
self.span_bug(sp, format!("impossible case reached: {}", msg));
|
||||
}
|
||||
pub fn verbose(&self) -> bool { self.debugging_opt(VERBOSE) }
|
||||
pub fn time_passes(&self) -> bool { self.debugging_opt(TIME_PASSES) }
|
||||
pub fn verbose(&self) -> bool { self.debugging_opt(config::VERBOSE) }
|
||||
pub fn time_passes(&self) -> bool { self.debugging_opt(config::TIME_PASSES) }
|
||||
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 {
|
||||
self.debugging_opt(COUNT_TYPE_SIZES)
|
||||
self.debugging_opt(config::COUNT_TYPE_SIZES)
|
||||
}
|
||||
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 meta_stats(&self) -> bool { self.debugging_opt(META_STATS) }
|
||||
pub fn asm_comments(&self) -> bool { self.debugging_opt(ASM_COMMENTS) }
|
||||
pub fn no_verify(&self) -> bool { self.debugging_opt(NO_VERIFY) }
|
||||
pub fn borrowck_stats(&self) -> bool { self.debugging_opt(BORROWCK_STATS) }
|
||||
pub fn trans_stats(&self) -> bool { self.debugging_opt(config::TRANS_STATS) }
|
||||
pub fn meta_stats(&self) -> bool { self.debugging_opt(config::META_STATS) }
|
||||
pub fn asm_comments(&self) -> bool { self.debugging_opt(config::ASM_COMMENTS) }
|
||||
pub fn no_verify(&self) -> bool { self.debugging_opt(config::NO_VERIFY) }
|
||||
pub fn borrowck_stats(&self) -> bool { self.debugging_opt(config::BORROWCK_STATS) }
|
||||
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 {
|
||||
self.debugging_opt(LTO)
|
||||
self.debugging_opt(config::LTO)
|
||||
}
|
||||
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 {
|
||||
self.debugging_opt(SHOW_SPAN)
|
||||
self.debugging_opt(config::SHOW_SPAN)
|
||||
}
|
||||
pub fn sysroot<'a>(&'a self) -> &'a Path {
|
||||
match self.opts.maybe_sysroot {
|
||||
@ -333,142 +188,63 @@ impl Session {
|
||||
pub fn host_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
|
||||
filesearch::FileSearch::new(
|
||||
self.sysroot(),
|
||||
host_triple(),
|
||||
driver::host_triple(),
|
||||
&self.opts.addl_lib_search_paths)
|
||||
}
|
||||
}
|
||||
|
||||
/// 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: 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(),
|
||||
pub fn build_session(sopts: config::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: config::Options,
|
||||
local_crate_source_file: Option<Path>,
|
||||
span_diagnostic: diagnostic::SpanHandler)
|
||||
-> Session {
|
||||
let target_cfg = config::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),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
// except according to those terms.
|
||||
|
||||
use driver::session;
|
||||
use driver::config;
|
||||
use driver::session::Session;
|
||||
|
||||
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| {
|
||||
*ty == session::CrateTypeExecutable
|
||||
*ty == config::CrateTypeExecutable
|
||||
});
|
||||
if use_start(&krate) && any_exe {
|
||||
vis.push(ast::ViewItem {
|
||||
|
@ -44,23 +44,6 @@ extern crate libc;
|
||||
#[phase(syntax, link)]
|
||||
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 trans;
|
||||
pub mod ty;
|
||||
@ -136,309 +119,8 @@ pub mod lib {
|
||||
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() {
|
||||
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::svh::Svh;
|
||||
use driver::session::Session;
|
||||
use driver::{driver, session};
|
||||
use driver::{driver, config};
|
||||
use metadata::cstore;
|
||||
use metadata::cstore::CStore;
|
||||
use metadata::decoder;
|
||||
@ -331,7 +331,7 @@ fn resolve_crate<'a>(e: &mut Env,
|
||||
id_hash: id_hash,
|
||||
hash: hash.map(|a| &*a),
|
||||
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(),
|
||||
root: root,
|
||||
rejected_via_hash: vec!(),
|
||||
@ -387,7 +387,7 @@ impl<'a> CrateLoader for Loader<'a> {
|
||||
let is_cross = target_triple != driver::host_triple();
|
||||
let mut should_link = info.should_link && !is_cross;
|
||||
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 {
|
||||
sess: self.env.sess,
|
||||
span: krate.span,
|
||||
@ -397,7 +397,7 @@ impl<'a> CrateLoader for Loader<'a> {
|
||||
hash: None,
|
||||
filesearch: self.env.sess.host_filesearch(),
|
||||
triple: driver::host_triple(),
|
||||
os: session::sess_os_to_meta_os(os),
|
||||
os: config::cfg_os_to_meta_os(os),
|
||||
root: &None,
|
||||
rejected_via_hash: 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
|
||||
// no syntax extensions)
|
||||
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();
|
||||
let lib = load_ctxt.load_library_crate();
|
||||
if decoder::get_macro_registrar_fn(lib.metadata.as_slice()).is_some() {
|
||||
|
@ -14,7 +14,7 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use back::svh::Svh;
|
||||
use driver::session;
|
||||
use driver::config;
|
||||
use metadata::common::*;
|
||||
use metadata::cstore;
|
||||
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) {
|
||||
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) => {
|
||||
let s = arr.iter().enumerate().filter_map(|(i, slot)| {
|
||||
slot.map(|kind| format!("{}:{}", i + 1, match kind {
|
||||
|
@ -65,6 +65,7 @@ use collections::HashMap;
|
||||
use syntax::ast;
|
||||
|
||||
use driver::session;
|
||||
use driver::config;
|
||||
use metadata::cstore;
|
||||
use metadata::csearch;
|
||||
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.
|
||||
///
|
||||
/// 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) {
|
||||
let mut fmts = tcx.dependency_formats.borrow_mut();
|
||||
@ -91,11 +92,11 @@ pub fn calculate(tcx: &ty::ctxt) {
|
||||
}
|
||||
|
||||
fn calculate_type(sess: &session::Session,
|
||||
ty: session::CrateType) -> DependencyList {
|
||||
ty: config::CrateType) -> DependencyList {
|
||||
match ty {
|
||||
// If the global prefer_dynamic switch is turned off, first attempt
|
||||
// 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) {
|
||||
Some(v) => return v,
|
||||
None => {}
|
||||
@ -104,11 +105,11 @@ fn calculate_type(sess: &session::Session,
|
||||
|
||||
// No linkage happens with rlibs, we just needed the metadata (which we
|
||||
// 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
|
||||
// found, we generate some nice pretty errors.
|
||||
session::CrateTypeStaticlib => {
|
||||
config::CrateTypeStaticlib => {
|
||||
match attempt_static(sess) {
|
||||
Some(v) => return v,
|
||||
None => {}
|
||||
@ -123,7 +124,7 @@ fn calculate_type(sess: &session::Session,
|
||||
}
|
||||
|
||||
// Everything else falls through below
|
||||
session::CrateTypeExecutable | session::CrateTypeDylib => {},
|
||||
config::CrateTypeExecutable | config::CrateTypeDylib => {},
|
||||
}
|
||||
|
||||
let mut formats = HashMap::new();
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
use driver::session;
|
||||
use driver::config;
|
||||
use driver::session::Session;
|
||||
use syntax::ast::{Crate, Name, NodeId, Item, ItemFn};
|
||||
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) {
|
||||
let any_exe = session.crate_types.borrow().iter().any(|ty| {
|
||||
*ty == session::CrateTypeExecutable
|
||||
*ty == config::CrateTypeExecutable
|
||||
});
|
||||
if !any_exe {
|
||||
// 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 attr::contains_name(krate.attrs.as_slice(), "no_main") {
|
||||
session.entry_type.set(Some(session::EntryNone));
|
||||
session.entry_type.set(Some(config::EntryNone));
|
||||
return
|
||||
}
|
||||
|
||||
@ -127,13 +127,13 @@ fn find_item(item: &Item, ctxt: &mut EntryContext) {
|
||||
fn configure_main(this: &mut EntryContext) {
|
||||
if this.start_fn.is_some() {
|
||||
*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() {
|
||||
*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() {
|
||||
*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 {
|
||||
// No main function
|
||||
this.session.err("main function not found");
|
||||
|
@ -15,7 +15,7 @@
|
||||
// makes all other generics or inline functions that it references
|
||||
// reachable as well.
|
||||
|
||||
use driver::session;
|
||||
use driver::config;
|
||||
use middle::ty;
|
||||
use middle::typeck;
|
||||
use middle::privacy;
|
||||
@ -162,7 +162,7 @@ impl<'a> ReachableContext<'a> {
|
||||
// Creates a new reachability computation context.
|
||||
fn new(tcx: &'a ty::ctxt) -> ReachableContext<'a> {
|
||||
let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| {
|
||||
*ty != session::CrateTypeExecutable
|
||||
*ty != config::CrateTypeExecutable
|
||||
});
|
||||
ReachableContext {
|
||||
tcx: tcx,
|
||||
|
@ -195,7 +195,7 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use back::abi;
|
||||
use driver::session::FullDebugInfo;
|
||||
use driver::config::FullDebugInfo;
|
||||
use lib::llvm::{llvm, ValueRef, BasicBlockRef};
|
||||
use middle::const_eval;
|
||||
use middle::lang_items::{UniqStrEqFnLangItem, StrEqFnLangItem};
|
||||
|
@ -27,8 +27,9 @@
|
||||
|
||||
use back::link::{mangle_exported_name};
|
||||
use back::{link, abi};
|
||||
use driver::session;
|
||||
use driver::session::{Session, NoDebugInfo, FullDebugInfo};
|
||||
use driver::config;
|
||||
use driver::config::{NoDebugInfo, FullDebugInfo};
|
||||
use driver::session::Session;
|
||||
use driver::driver::OutputFilenames;
|
||||
use driver::driver::{CrateAnalysis, CrateTranslation};
|
||||
use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
|
||||
@ -1725,11 +1726,11 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
|
||||
main_llfn: ValueRef) {
|
||||
let et = ccx.sess().entry_type.get().unwrap();
|
||||
match et {
|
||||
session::EntryMain => {
|
||||
config::EntryMain => {
|
||||
create_entry_fn(ccx, main_llfn, true);
|
||||
}
|
||||
session::EntryStart => create_entry_fn(ccx, main_llfn, false),
|
||||
session::EntryNone => {} // Do nothing.
|
||||
config::EntryStart => create_entry_fn(ccx, main_llfn, false),
|
||||
config::EntryNone => {} // Do nothing.
|
||||
}
|
||||
|
||||
fn create_entry_fn(ccx: &CrateContext,
|
||||
@ -2068,7 +2069,7 @@ pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec<u8> {
|
||||
use flate;
|
||||
|
||||
let any_library = cx.sess().crate_types.borrow().iter().any(|ty| {
|
||||
*ty != session::CrateTypeExecutable
|
||||
*ty != config::CrateTypeExecutable
|
||||
});
|
||||
if !any_library {
|
||||
return Vec::new()
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
use back::abi;
|
||||
use back::link::mangle_internal_name_by_path_and_seq;
|
||||
use driver::session::FullDebugInfo;
|
||||
use driver::config::FullDebugInfo;
|
||||
use lib::llvm::ValueRef;
|
||||
use middle::freevars;
|
||||
use middle::lang_items::ClosureExchangeMallocFnLangItem;
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
use driver::session::NoDebugInfo;
|
||||
use driver::config::NoDebugInfo;
|
||||
use driver::session::Session;
|
||||
use lib::llvm::{ContextRef, ModuleRef, ValueRef};
|
||||
use lib::llvm::{llvm, TargetData, TypeNames};
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use lib::llvm::*;
|
||||
use driver::session::FullDebugInfo;
|
||||
use driver::config::FullDebugInfo;
|
||||
use middle::lang_items::{FailFnLangItem, FailBoundsCheckFnLangItem};
|
||||
use middle::trans::base::*;
|
||||
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::session::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
||||
use driver::config;
|
||||
use driver::config::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
||||
use lib::llvm::llvm;
|
||||
use lib::llvm::{ModuleRef, ContextRef, ValueRef};
|
||||
use lib::llvm::debuginfo::*;
|
||||
@ -748,7 +748,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
|
||||
true,
|
||||
scope_line as c_uint,
|
||||
FlagPrototyped as c_uint,
|
||||
cx.sess().opts.optimize != session::No,
|
||||
cx.sess().opts.optimize != config::No,
|
||||
llfn,
|
||||
template_parameters,
|
||||
ptr::null())
|
||||
@ -981,7 +981,7 @@ fn compile_unit_metadata(cx: &CrateContext) {
|
||||
compile_unit_name,
|
||||
work_dir,
|
||||
producer,
|
||||
cx.sess().opts.optimize != session::No,
|
||||
cx.sess().opts.optimize != config::No,
|
||||
flags,
|
||||
0,
|
||||
split_name);
|
||||
@ -1032,7 +1032,7 @@ fn declare_local(bcx: &Block,
|
||||
file_metadata,
|
||||
loc.line as c_uint,
|
||||
type_metadata,
|
||||
cx.sess().opts.optimize != session::No,
|
||||
cx.sess().opts.optimize != config::No,
|
||||
0,
|
||||
argument_index)
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ independently:
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use driver::session;
|
||||
use driver::config;
|
||||
|
||||
use middle::resolve;
|
||||
use middle::ty;
|
||||
@ -414,9 +414,9 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
|
||||
let tcx = ccx.tcx;
|
||||
match *tcx.sess.entry_fn.borrow() {
|
||||
Some((id, sp)) => match tcx.sess.entry_type.get() {
|
||||
Some(session::EntryMain) => check_main_fn_ty(ccx, id, sp),
|
||||
Some(session::EntryStart) => check_start_fn_ty(ccx, id, sp),
|
||||
Some(session::EntryNone) => {}
|
||||
Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp),
|
||||
Some(config::EntryStart) => check_start_fn_ty(ccx, id, sp),
|
||||
Some(config::EntryNone) => {}
|
||||
None => tcx.sess.bug("entry function without a type")
|
||||
},
|
||||
None => {}
|
||||
|
@ -60,19 +60,20 @@ pub struct CrateAnalysis {
|
||||
fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<~str>)
|
||||
-> (DocContext, CrateAnalysis) {
|
||||
use syntax::codemap::dummy_spanned;
|
||||
use rustc::driver::driver::{FileInput, build_configuration,
|
||||
use rustc::driver::driver::{FileInput,
|
||||
phase_1_parse_input,
|
||||
phase_2_configure_and_expand,
|
||||
phase_3_run_analysis_passes};
|
||||
use rustc::driver::config::build_configuration;
|
||||
|
||||
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()),
|
||||
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)),
|
||||
..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 =
|
||||
syntax::diagnostic::mk_span_handler(diagnostic_handler, codemap);
|
||||
|
||||
let sess = driver::driver::build_session_(sessopts,
|
||||
Some(cpath.clone()),
|
||||
span_diagnostic_handler);
|
||||
let sess = driver::session::build_session_(sessopts,
|
||||
Some(cpath.clone()),
|
||||
span_diagnostic_handler);
|
||||
|
||||
let mut cfg = build_configuration(&sess);
|
||||
for cfg_ in cfgs.move_iter() {
|
||||
|
@ -145,7 +145,7 @@ pub fn main_args(args: &[~str]) -> int {
|
||||
usage(args[0]);
|
||||
return 0;
|
||||
} else if matches.opt_present("version") {
|
||||
rustc::version(args[0]);
|
||||
rustc::driver::version(args[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ use std::strbuf::StrBuf;
|
||||
use collections::{HashSet, HashMap};
|
||||
use testing;
|
||||
use rustc::back::link;
|
||||
use rustc::driver::config;
|
||||
use rustc::driver::driver;
|
||||
use rustc::driver::session;
|
||||
use rustc::metadata::creader::Loader;
|
||||
@ -43,11 +44,11 @@ pub fn run(input: &str,
|
||||
let input_path = Path::new(input);
|
||||
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()),
|
||||
addl_lib_search_paths: RefCell::new(libs.clone()),
|
||||
crate_types: vec!(session::CrateTypeDylib),
|
||||
..session::basic_options().clone()
|
||||
crate_types: vec!(config::CrateTypeDylib),
|
||||
..config::basic_options().clone()
|
||||
};
|
||||
|
||||
|
||||
@ -56,11 +57,11 @@ pub fn run(input: &str,
|
||||
let span_diagnostic_handler =
|
||||
diagnostic::mk_span_handler(diagnostic_handler, codemap);
|
||||
|
||||
let sess = driver::build_session_(sessopts,
|
||||
let sess = session::build_session_(sessopts,
|
||||
Some(input_path.clone()),
|
||||
span_diagnostic_handler);
|
||||
|
||||
let mut cfg = driver::build_configuration(&sess);
|
||||
let mut cfg = config::build_configuration(&sess);
|
||||
cfg.extend(cfgs.move_iter().map(|cfg_| {
|
||||
let cfg_ = token::intern_and_get_ident(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 input = driver::StrInput(test);
|
||||
|
||||
let sessopts = session::Options {
|
||||
let sessopts = config::Options {
|
||||
maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
|
||||
addl_lib_search_paths: RefCell::new(libs),
|
||||
crate_types: vec!(session::CrateTypeExecutable),
|
||||
crate_types: vec!(config::CrateTypeExecutable),
|
||||
output_types: vec!(link::OutputTypeExe),
|
||||
no_trans: no_run,
|
||||
cg: session::CodegenOptions {
|
||||
cg: config::CodegenOptions {
|
||||
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
|
||||
@ -142,13 +143,13 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
|
||||
let span_diagnostic_handler =
|
||||
diagnostic::mk_span_handler(diagnostic_handler, codemap);
|
||||
|
||||
let sess = driver::build_session_(sessopts,
|
||||
let sess = session::build_session_(sessopts,
|
||||
None,
|
||||
span_diagnostic_handler);
|
||||
|
||||
let outdir = TempDir::new("rustdoctest").expect("rustdoc needs a tempdir");
|
||||
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);
|
||||
|
||||
if no_run { return }
|
||||
|
Loading…
x
Reference in New Issue
Block a user