diff --git a/src/librustc/back/arm.rs b/src/librustc/back/arm.rs index 798b5eadef4b7..792992833a218 100644 --- a/src/librustc/back/arm.rs +++ b/src/librustc/back/arm.rs @@ -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 => { diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 9fa3553cbfc9d..45641d08d1e35 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -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 { diff --git a/src/librustc/back/lto.rs b/src/librustc/back/lto.rs index 8319be02bdbc3..f581b7a38a80e 100644 --- a/src/librustc/back/lto.rs +++ b/src/librustc/back/lto.rs @@ -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"); diff --git a/src/librustc/back/mips.rs b/src/librustc/back/mips.rs index e318ffe5c9a21..ddf67ae564a3e 100644 --- a/src/librustc/back/mips.rs +++ b/src/librustc/back/mips.rs @@ -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 => { diff --git a/src/librustc/back/x86.rs b/src/librustc/back/x86.rs index 08ea29c2012ec..b572b59cf6e3b 100644 --- a/src/librustc/back/x86.rs +++ b/src/librustc/back/x86.rs @@ -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 => { diff --git a/src/librustc/back/x86_64.rs b/src/librustc/back/x86_64.rs index 68de14a524854..58f1a72e03c62 100644 --- a/src/librustc/back/x86_64.rs +++ b/src/librustc/back/x86_64.rs @@ -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 => { diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs new file mode 100644 index 0000000000000..ef8c8f1f70a47 --- /dev/null +++ b/src/librustc/driver/config.rs @@ -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 or the MIT license +// , 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, + + pub gc: bool, + pub optimize: OptLevel, + pub debuginfo: DebugInfoLevel, + pub lint_opts: Vec<(lint::Lint, lint::level)> , + pub output_types: Vec , + // 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>, + pub maybe_sysroot: Option, + 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), + /// 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}=)", + 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::>().append(default_cfg.as_slice()) +} + +pub fn get_os(triple: &str) -> Option { + 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 { + 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 { + 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"), + optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"), + optopt( "", "out-dir", "Write output to compiler-chosen filename in ", "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 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::() +} + +pub fn build_session_options(matches: &getopts::Matches) -> Options { + let mut crate_types: Vec = 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::>().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()); + } +} diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 701117edb4783..19f2d33e5b1eb 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -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, + output: &Option) { + // 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::>().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::() -} - 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, output: &Option) { - // 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) { let krate = phase_1_parse_input(&sess, cfg, input); let id = link::find_crate_id(krate.attrs.as_slice(), input.filestem()); @@ -727,405 +648,60 @@ pub fn pretty_print_input(sess: Session, } -pub fn get_os(triple: &str) -> Option { - for &(name, os) in os_names.iter() { - if triple.contains(name) { return Some(os) } +pub fn collect_crate_types(session: &Session, + attrs: &[ast::Attribute]) -> Vec { + // 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) } - 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 { - 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 = Vec::new(); - let unparsed_crate_types = matches.opt_strs("crate-type"); - for unparsed_crate_type in unparsed_crate_types.iter() { - for part in unparsed_crate_type.split(',') { - let new_part = match part { - "lib" => session::default_lib_output(), - "rlib" => session::CrateTypeRlib, - "staticlib" => session::CrateTypeStaticlib, - "dylib" => session::CrateTypeDylib, - "bin" => session::CrateTypeExecutable, - _ => early_error(format!("unknown crate type: `{}`", part)) - }; - crate_types.push(new_part) - } - } - - let parse_only = matches.opt_present("parse-only"); - 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::>().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}=)", - 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)); - } - } - return cg; -} - -pub fn build_session(sopts: session::Options, - local_crate_source_file: Option) - -> 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, - 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`"); + }); + base.extend(iter); + if base.len() == 0 { + base.push(config::CrateTypeExecutable); } + base.as_mut_slice().sort(); + base.dedup(); + return base; } } -// rustc command line options -pub fn optgroups() -> Vec { - 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"), - optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"), - optopt( "", "out-dir", "Write output to compiler-chosen filename in ", "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 after compiling, \ - in a format suitable for use by Makefiles", "FILENAME"), - optopt("", "sysroot", "Override the system root", "PATH"), - optflag("", "test", "Build a test harness"), - optopt("", "target", "Target triple cpu-manufacturer-kernel[-os] - to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/ - for details)", "TRIPLE"), - optmulti("W", "warn", "Set lint warnings", "OPT"), - optmulti("A", "allow", "Set lint allowed", "OPT"), - optmulti("D", "deny", "Set lint denied", "OPT"), - optmulti("F", "forbid", "Set lint forbidden", "OPT"), - optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"), - optmulti("Z", "", "Set internal debugging options", "FLAG"), - optflag( "v", "version", "Print version info and exit")) -} - pub struct OutputFilenames { pub out_directory: Path, pub out_filestem: ~str, @@ -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()); - } -} diff --git a/src/librustc/driver/mod.rs b/src/librustc/driver/mod.rs index 2508e6d8aabc6..ec60e2c3e6fcb 100644 --- a/src/librustc/driver/mod.rs +++ b/src/librustc/driver/mod.rs @@ -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::(ppm) => { + driver::pretty_print_input(sess, cfg, &input, ppm, ofile); + return; + } + None:: => {/* 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 Warn about + -A Allow + -D Deny + -F Forbid (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:: >(); + 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 { + 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::>().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, + ofile: &Option) + -> 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 { + 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::() { + let mut emitter = diagnostic::EmitterWriter::stderr(); + + // a .span_bug or .bug call has already printed what + // it wants to print. + if !value.is::() { + 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!(); + } + } +} diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 859647b1beb47..24921efdb782e 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -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, - - pub gc: bool, - pub optimize: OptLevel, - pub debuginfo: DebugInfoLevel, - pub lint_opts: Vec<(lint::Lint, lint::level)> , - pub output_types: Vec , - // 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>, - pub maybe_sysroot: Option, - 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), - /// 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>, - pub entry_type: Cell>, + pub entry_type: Cell>, pub macro_registrar_fn: Cell>, pub default_sysroot: Option, // 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>>, pub node_id: Cell, - pub crate_types: RefCell>, + pub crate_types: RefCell>, 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(), - } -} - -/// 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) - } - )* +pub fn build_session(sopts: config::Options, + local_crate_source_file: Option) + -> Session { + let codemap = codemap::CodeMap::new(); + let diagnostic_handler = + diagnostic::default_handler(); + let span_diagnostic_handler = + diagnostic::mk_span_handler(diagnostic_handler, codemap); - 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, - } - } + build_session_(sopts, local_crate_source_file, span_diagnostic_handler) +} - 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, - } +pub fn build_session_(sopts: config::Options, + local_crate_source_file: Option, + 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), } -) ) +} -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(sess: &Session, opt: Option, msg: || -> StrBuf) @@ -476,72 +252,3 @@ pub fn expect(sess: &Session, opt: Option, 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 { - // 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 - } -} diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs index 959197e5b2b02..da1f7bce89bc9 100644 --- a/src/librustc/front/std_inject.rs +++ b/src/librustc/front/std_inject.rs @@ -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 { diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 0962acd0a2ebf..5b5ec2cdc2157 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -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 Warn about - -A Allow - -D Deny - -F Forbid (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:: >(); - 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::>().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::(ppm) => { - d::pretty_print_input(sess, cfg, &input, ppm, ofile); - return; - } - None:: => {/* 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 { - 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::() { - let mut emitter = diagnostic::EmitterWriter::stderr(); - - // a .span_bug or .bug call has already printed what - // it wants to print. - if !value.is::() { - 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 -} diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index a5675f52671fe..d0b14f9e1302a 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -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() { diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 5faae72791d7e..10d26922f750f 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -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 { diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 7b5ef2bf2be62..ae88d64e2f0c9 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -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>; /// 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; +pub type Dependencies = HashMap; 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(); diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index a17c8fb5c433e..1b7ed90237fd9 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -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"); diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 7dad6473478c1..49e607f12406c 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -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, diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index b456ec224fe7e..abb9be62dd8d4 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -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}; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 6c4566c09aa7a..4562f27536fc8 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -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}; @@ -1724,11 +1725,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, @@ -2067,7 +2068,7 @@ pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec { 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() diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index bfbd638be520c..1f4ea02bcc648 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -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; diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index f46c323232657..777c03fa6068b 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -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}; diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index a165549dacabb..ec43e6e286f7d 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -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::*; diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 304aa9b4025b5..1e56604983f5f 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -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) } diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 49297e919ec60..83300f6dba705 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -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 => {} diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index d65d5a1e458e6..e2684b3be693e 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -60,19 +60,20 @@ pub struct CrateAnalysis { fn get_ast_and_resolve(cpath: &Path, libs: HashSet, 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, 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() { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 72b474147335c..3e87a2539c28a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -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; } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index c8a19183485e1..8a631fdcdd08c 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -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, 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, 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 }