]> git.lizzy.rs Git - rust.git/commitdiff
Reorganise driver code.
authorNick Cameron <ncameron@mozilla.com>
Tue, 6 May 2014 11:38:01 +0000 (23:38 +1200)
committerNick Cameron <ncameron@mozilla.com>
Sat, 10 May 2014 23:08:01 +0000 (11:08 +1200)
The goal of this refactoring is to make the rustc driver code easier to understand and use. Since this is as close to an API as we have, I think it is important that it is nice. On getting stuck in, I found that there wasn't as much to change as I'd hoped to make the stage... fns easier to use by tools.

This patch only moves code around - mostly just moving code to different files, but a few extracted method refactorings too. To summarise the changes: I added driver::config which handles everything about configuring the compiler. driver::session now just defines and builds session objects. I moved driver code from librustc/lib.rs to librustc/driver/mod.rs so all the code is one place. I extracted methods to make emulating the compiler without being the compiler a little easier. Within the driver directory, I moved code around to more logically fit in the modules.

27 files changed:
src/librustc/back/arm.rs
src/librustc/back/link.rs
src/librustc/back/lto.rs
src/librustc/back/mips.rs
src/librustc/back/x86.rs
src/librustc/back/x86_64.rs
src/librustc/driver/config.rs [new file with mode: 0644]
src/librustc/driver/driver.rs
src/librustc/driver/mod.rs
src/librustc/driver/session.rs
src/librustc/front/std_inject.rs
src/librustc/lib.rs
src/librustc/metadata/creader.rs
src/librustc/metadata/encoder.rs
src/librustc/middle/dependency_format.rs
src/librustc/middle/entry.rs
src/librustc/middle/reachable.rs
src/librustc/middle/trans/_match.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/closure.rs
src/librustc/middle/trans/context.rs
src/librustc/middle/trans/controlflow.rs
src/librustc/middle/trans/debuginfo.rs
src/librustc/middle/typeck/mod.rs
src/librustdoc/core.rs
src/librustdoc/lib.rs
src/librustdoc/test.rs

index 798b5eadef4b79e1c3810776a21ef5ec50681c8e..792992833a218e3f9709d121c0618c41c7fa436b 100644 (file)
@@ -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 => {
index 9fa3553cbfc9d8f382735219da4f0759aa6089d9..45641d08d1e351ae461c413f98919256526bbf14 100644 (file)
@@ -12,8 +12,9 @@
 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 fn run_passes(sess: &Session,
             }
 
             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 fn run_passes(sess: &Session,
             // 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 @@ unsafe fn configure_llvm(sess: &Session) {
         // 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 {
index 8319be02bdbc301705f2ea27564861e38be78715..f581b7a38a80e2b7ad2996fbba3c959c145f9870 100644 (file)
@@ -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");
index e318ffe5c9a219c21b8e74c4cd8203222746d1f3..ddf67ae564a3eaa18e52ea4fc98a1605272e056b 100644 (file)
@@ -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 => {
index 08ea29c2012ecc0586a78bd381d6548a4f27d0a0..b572b59cf6e3b337f05e3609a4d33d7d12964ec1 100644 (file)
@@ -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 => {
index 68de14a5248546567bf29c8d8fd3b560f167e202..58f1a72e03c62c1fc9c2fb9d3490a1582c7a96b0 100644 (file)
@@ -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 (file)
index 0000000..ef8c8f1
--- /dev/null
@@ -0,0 +1,769 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Contains infrastructure for configuring the compiler, including parsing
+//! command line options.
+
+use driver::early_error;
+use driver::driver;
+use driver::session::Session;
+
+use back;
+use back::link;
+use back::target_strs;
+use back::{arm, x86, x86_64, mips};
+use metadata;
+use middle::lint;
+
+use syntax::abi;
+use syntax::ast;
+use syntax::ast::{IntTy, UintTy};
+use syntax::attr;
+use syntax::attr::AttrMetaMethods;
+use syntax::parse;
+use syntax::parse::token::InternedString;
+
+use collections::HashSet;
+use getopts::{optopt, optmulti, optflag, optflagopt};
+use getopts;
+use lib::llvm::llvm;
+use std::cell::{RefCell};
+
+
+pub struct Config {
+    pub os: abi::Os,
+    pub arch: abi::Architecture,
+    pub target_strs: target_strs::t,
+    pub int_type: IntTy,
+    pub uint_type: UintTy,
+}
+
+#[deriving(Clone, Eq)]
+pub enum OptLevel {
+    No, // -O0
+    Less, // -O1
+    Default, // -O2
+    Aggressive // -O3
+}
+
+#[deriving(Clone, Eq)]
+pub enum DebugInfoLevel {
+    NoDebugInfo,
+    LimitedDebugInfo,
+    FullDebugInfo,
+}
+
+#[deriving(Clone)]
+pub struct Options {
+    // The crate config requested for the session, which may be combined
+    // with additional crate configurations during the compile process
+    pub crate_types: Vec<CrateType>,
+
+    pub gc: bool,
+    pub optimize: OptLevel,
+    pub debuginfo: DebugInfoLevel,
+    pub lint_opts: Vec<(lint::Lint, lint::level)> ,
+    pub output_types: Vec<back::link::OutputType> ,
+    // This was mutable for rustpkg, which updates search paths based on the
+    // parsed code. It remains mutable in case its replacements wants to use
+    // this.
+    pub addl_lib_search_paths: RefCell<HashSet<Path>>,
+    pub maybe_sysroot: Option<Path>,
+    pub target_triple: ~str,
+    // User-specified cfg meta items. The compiler itself will add additional
+    // items to the crate config, and during parsing the entire crate config
+    // will be added to the crate AST node.  This should not be used for
+    // anything except building the full crate config prior to parsing.
+    pub cfg: ast::CrateConfig,
+    pub test: bool,
+    pub parse_only: bool,
+    pub no_trans: bool,
+    pub no_analysis: bool,
+    pub debugging_opts: u64,
+    /// Whether to write dependency files. It's (enabled, optional filename).
+    pub write_dependency_info: (bool, Option<Path>),
+    /// Crate id-related things to maybe print. It's (crate_id, crate_name, crate_file_name).
+    pub print_metas: (bool, bool, bool),
+    pub cg: CodegenOptions,
+}
+
+/// Some reasonable defaults
+pub fn basic_options() -> Options {
+    Options {
+        crate_types: Vec::new(),
+        gc: false,
+        optimize: No,
+        debuginfo: NoDebugInfo,
+        lint_opts: Vec::new(),
+        output_types: Vec::new(),
+        addl_lib_search_paths: RefCell::new(HashSet::new()),
+        maybe_sysroot: None,
+        target_triple: driver::host_triple().to_owned(),
+        cfg: Vec::new(),
+        test: false,
+        parse_only: false,
+        no_trans: false,
+        no_analysis: false,
+        debugging_opts: 0,
+        write_dependency_info: (false, None),
+        print_metas: (false, false, false),
+        cg: basic_codegen_options(),
+    }
+}
+
+// The type of entry function, so
+// users can have their own entry
+// functions that don't start a
+// scheduler
+#[deriving(Eq)]
+pub enum EntryFnType {
+    EntryMain,
+    EntryStart,
+    EntryNone,
+}
+
+#[deriving(Eq, Ord, Clone, TotalOrd, TotalEq, Hash)]
+pub enum CrateType {
+    CrateTypeExecutable,
+    CrateTypeDylib,
+    CrateTypeRlib,
+    CrateTypeStaticlib,
+}
+
+macro_rules! debugging_opts(
+    ([ $opt:ident ] $cnt:expr ) => (
+        pub static $opt: u64 = 1 << $cnt;
+    );
+    ([ $opt:ident, $($rest:ident),* ] $cnt:expr ) => (
+        pub static $opt: u64 = 1 << $cnt;
+        debugging_opts!([ $($rest),* ] $cnt + 1)
+    )
+)
+
+debugging_opts!(
+    [
+        VERBOSE,
+        TIME_PASSES,
+        COUNT_LLVM_INSNS,
+        TIME_LLVM_PASSES,
+        TRANS_STATS,
+        ASM_COMMENTS,
+        NO_VERIFY,
+        BORROWCK_STATS,
+        NO_LANDING_PADS,
+        DEBUG_LLVM,
+        SHOW_SPAN,
+        COUNT_TYPE_SIZES,
+        META_STATS,
+        NO_OPT,
+        GC,
+        PRINT_LINK_ARGS,
+        PRINT_LLVM_PASSES,
+        LTO,
+        AST_JSON,
+        AST_JSON_NOEXPAND,
+        LS
+    ]
+    0
+)
+
+pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
+    vec!(("verbose", "in general, enable more debug printouts", VERBOSE),
+     ("time-passes", "measure time of each rustc pass", TIME_PASSES),
+     ("count-llvm-insns", "count where LLVM \
+                           instrs originate", COUNT_LLVM_INSNS),
+     ("time-llvm-passes", "measure time of each LLVM pass",
+      TIME_LLVM_PASSES),
+     ("trans-stats", "gather trans statistics", TRANS_STATS),
+     ("asm-comments", "generate comments into the assembly (may change behavior)",
+      ASM_COMMENTS),
+     ("no-verify", "skip LLVM verification", NO_VERIFY),
+     ("borrowck-stats", "gather borrowck statistics",  BORROWCK_STATS),
+     ("no-landing-pads", "omit landing pads for unwinding",
+      NO_LANDING_PADS),
+     ("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM),
+     ("show-span", "show spans for compiler debugging", SHOW_SPAN),
+     ("count-type-sizes", "count the sizes of aggregate types",
+      COUNT_TYPE_SIZES),
+     ("meta-stats", "gather metadata statistics", META_STATS),
+     ("no-opt", "do not optimize, even if -O is passed", NO_OPT),
+     ("print-link-args", "Print the arguments passed to the linker",
+      PRINT_LINK_ARGS),
+     ("gc", "Garbage collect shared data (experimental)", GC),
+     ("print-llvm-passes",
+      "Prints the llvm optimization passes being run",
+      PRINT_LLVM_PASSES),
+     ("lto", "Perform LLVM link-time optimizations", LTO),
+     ("ast-json", "Print the AST as JSON and halt", AST_JSON),
+     ("ast-json-noexpand", "Print the pre-expansion AST as JSON and halt", AST_JSON_NOEXPAND),
+     ("ls", "List the symbols defined by a library crate", LS))
+}
+
+/// Declare a macro that will define all CodegenOptions fields and parsers all
+/// at once. The goal of this macro is to define an interface that can be
+/// programmatically used by the option parser in order to initialize the struct
+/// without hardcoding field names all over the place.
+///
+/// The goal is to invoke this macro once with the correct fields, and then this
+/// macro generates all necessary code. The main gotcha of this macro is the
+/// cgsetters module which is a bunch of generated code to parse an option into
+/// its respective field in the struct. There are a few hand-written parsers for
+/// parsing specific types of values in this module.
+macro_rules! cgoptions(
+    ($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
+(
+    #[deriving(Clone)]
+    pub struct CodegenOptions { $(pub $opt: $t),* }
+
+    pub fn basic_codegen_options() -> CodegenOptions {
+        CodegenOptions { $($opt: $init),* }
+    }
+
+    pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool;
+    pub static CG_OPTIONS: &'static [(&'static str, CodegenSetter,
+                                      &'static str)] =
+        &[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ];
+
+    mod cgsetters {
+        use super::CodegenOptions;
+
+        $(
+            pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool {
+                $parse(&mut cg.$opt, v)
+            }
+        )*
+
+        fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
+            match v {
+                Some(..) => false,
+                None => { *slot = true; true }
+            }
+        }
+
+        fn parse_opt_string(slot: &mut Option<~str>, v: Option<&str>) -> bool {
+            match v {
+                Some(s) => { *slot = Some(s.to_owned()); true },
+                None => false,
+            }
+        }
+
+        fn parse_string(slot: &mut ~str, v: Option<&str>) -> bool {
+            match v {
+                Some(s) => { *slot = s.to_owned(); true },
+                None => false,
+            }
+        }
+
+        fn parse_list(slot: &mut Vec<~str>, v: Option<&str>)
+                      -> bool {
+            match v {
+                Some(s) => {
+                    for s in s.words() {
+                        slot.push(s.to_owned());
+                    }
+                    true
+                },
+                None => false,
+            }
+        }
+
+    }
+) )
+
+cgoptions!(
+    ar: Option<~str> = (None, parse_opt_string,
+        "tool to assemble archives with"),
+    linker: Option<~str> = (None, parse_opt_string,
+        "system linker to link outputs with"),
+    link_args: Vec<~str> = (Vec::new(), parse_list,
+        "extra arguments to pass to the linker (space separated)"),
+    target_cpu: ~str = ("generic".to_owned(), parse_string,
+        "select target processor (llc -mcpu=help for details)"),
+    target_feature: ~str = ("".to_owned(), parse_string,
+        "target specific attributes (llc -mattr=help for details)"),
+    passes: Vec<~str> = (Vec::new(), parse_list,
+        "a list of extra LLVM passes to run (space separated)"),
+    llvm_args: Vec<~str> = (Vec::new(), parse_list,
+        "a list of arguments to pass to llvm (space separated)"),
+    save_temps: bool = (false, parse_bool,
+        "save all temporary output files during compilation"),
+    android_cross_path: Option<~str> = (None, parse_opt_string,
+        "the path to the Android NDK"),
+    no_rpath: bool = (false, parse_bool,
+        "disables setting the rpath in libs/exes"),
+    no_prepopulate_passes: bool = (false, parse_bool,
+        "don't pre-populate the pass manager with a list of passes"),
+    no_vectorize_loops: bool = (false, parse_bool,
+        "don't run the loop vectorization optimization passes"),
+    no_vectorize_slp: bool = (false, parse_bool,
+        "don't run LLVM's SLP vectorization pass"),
+    soft_float: bool = (false, parse_bool,
+        "generate software floating point library calls"),
+    prefer_dynamic: bool = (false, parse_bool,
+        "prefer dynamic linking to static linking"),
+    no_integrated_as: bool = (false, parse_bool,
+        "use an external assembler rather than LLVM's integrated one"),
+    relocation_model: ~str = ("pic".to_owned(), parse_string,
+         "choose the relocation model to use (llc -relocation-model for details)"),
+)
+
+pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
+{
+    let mut cg = basic_codegen_options();
+    for option in matches.opt_strs("C").move_iter() {
+        let mut iter = option.splitn('=', 1);
+        let key = iter.next().unwrap();
+        let value = iter.next();
+        let option_to_lookup = key.replace("-", "_");
+        let mut found = false;
+        for &(candidate, setter, _) in CG_OPTIONS.iter() {
+            if option_to_lookup.as_slice() != candidate { continue }
+            if !setter(&mut cg, value) {
+                match value {
+                    Some(..) => early_error(format!("codegen option `{}` takes \
+                                                     no value", key)),
+                    None => early_error(format!("codegen option `{0}` requires \
+                                                 a value (-C {0}=<value>)",
+                                                key))
+                }
+            }
+            found = true;
+            break;
+        }
+        if !found {
+            early_error(format!("unknown codegen option: `{}`", key));
+        }
+    }
+    return cg;
+}
+
+pub fn default_lib_output() -> CrateType {
+    CrateTypeRlib
+}
+
+pub fn cfg_os_to_meta_os(os: abi::Os) -> metadata::loader::Os {
+    use metadata::loader;
+
+    match os {
+        abi::OsWin32 => loader::OsWin32,
+        abi::OsLinux => loader::OsLinux,
+        abi::OsAndroid => loader::OsAndroid,
+        abi::OsMacos => loader::OsMacos,
+        abi::OsFreebsd => loader::OsFreebsd
+    }
+}
+
+pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
+    let tos = match sess.targ_cfg.os {
+        abi::OsWin32 =>   InternedString::new("win32"),
+        abi::OsMacos =>   InternedString::new("macos"),
+        abi::OsLinux =>   InternedString::new("linux"),
+        abi::OsAndroid => InternedString::new("android"),
+        abi::OsFreebsd => InternedString::new("freebsd"),
+    };
+
+    // ARM is bi-endian, however using NDK seems to default
+    // to little-endian unless a flag is provided.
+    let (end,arch,wordsz) = match sess.targ_cfg.arch {
+        abi::X86 =>    ("little", "x86",    "32"),
+        abi::X86_64 => ("little", "x86_64", "64"),
+        abi::Arm =>    ("little", "arm",    "32"),
+        abi::Mips =>   ("big",    "mips",   "32")
+    };
+
+    let fam = match sess.targ_cfg.os {
+        abi::OsWin32 => InternedString::new("windows"),
+        _ => InternedString::new("unix")
+    };
+
+    let mk = attr::mk_name_value_item_str;
+    return vec!(// Target bindings.
+         attr::mk_word_item(fam.clone()),
+         mk(InternedString::new("target_os"), tos),
+         mk(InternedString::new("target_family"), fam),
+         mk(InternedString::new("target_arch"), InternedString::new(arch)),
+         mk(InternedString::new("target_endian"), InternedString::new(end)),
+         mk(InternedString::new("target_word_size"),
+            InternedString::new(wordsz))
+    );
+}
+
+pub fn append_configuration(cfg: &mut ast::CrateConfig,
+                            name: InternedString) {
+    if !cfg.iter().any(|mi| mi.name() == name) {
+        cfg.push(attr::mk_word_item(name))
+    }
+}
+
+pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
+    // Combine the configuration requested by the session (command line) with
+    // some default and generated configuration items
+    let default_cfg = default_configuration(sess);
+    let mut user_cfg = sess.opts.cfg.clone();
+    // If the user wants a test runner, then add the test cfg
+    if sess.opts.test {
+        append_configuration(&mut user_cfg, InternedString::new("test"))
+    }
+    // If the user requested GC, then add the GC cfg
+    append_configuration(&mut user_cfg, if sess.opts.gc {
+        InternedString::new("gc")
+    } else {
+        InternedString::new("nogc")
+    });
+    user_cfg.move_iter().collect::<Vec<_>>().append(default_cfg.as_slice())
+}
+
+pub fn get_os(triple: &str) -> Option<abi::Os> {
+    for &(name, os) in os_names.iter() {
+        if triple.contains(name) { return Some(os) }
+    }
+    None
+}
+static os_names : &'static [(&'static str, abi::Os)] = &'static [
+    ("mingw32", abi::OsWin32),
+    ("win32",   abi::OsWin32),
+    ("darwin",  abi::OsMacos),
+    ("android", abi::OsAndroid),
+    ("linux",   abi::OsLinux),
+    ("freebsd", abi::OsFreebsd)];
+
+pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
+    for &(arch, abi) in architecture_abis.iter() {
+        if triple.contains(arch) { return Some(abi) }
+    }
+    None
+}
+static architecture_abis : &'static [(&'static str, abi::Architecture)] = &'static [
+    ("i386",   abi::X86),
+    ("i486",   abi::X86),
+    ("i586",   abi::X86),
+    ("i686",   abi::X86),
+    ("i786",   abi::X86),
+
+    ("x86_64", abi::X86_64),
+
+    ("arm",    abi::Arm),
+    ("xscale", abi::Arm),
+    ("thumb",  abi::Arm),
+
+    ("mips",   abi::Mips)];
+
+pub fn build_target_config(sopts: &Options) -> Config {
+    let os = match get_os(sopts.target_triple) {
+      Some(os) => os,
+      None => early_error("unknown operating system")
+    };
+    let arch = match get_arch(sopts.target_triple) {
+      Some(arch) => arch,
+      None => early_error("unknown architecture: " + sopts.target_triple)
+    };
+    let (int_type, uint_type) = match arch {
+      abi::X86 => (ast::TyI32, ast::TyU32),
+      abi::X86_64 => (ast::TyI64, ast::TyU64),
+      abi::Arm => (ast::TyI32, ast::TyU32),
+      abi::Mips => (ast::TyI32, ast::TyU32)
+    };
+    let target_triple = sopts.target_triple.clone();
+    let target_strs = match arch {
+      abi::X86 => x86::get_target_strs(target_triple, os),
+      abi::X86_64 => x86_64::get_target_strs(target_triple, os),
+      abi::Arm => arm::get_target_strs(target_triple, os),
+      abi::Mips => mips::get_target_strs(target_triple, os)
+    };
+    Config {
+        os: os,
+        arch: arch,
+        target_strs: target_strs,
+        int_type: int_type,
+        uint_type: uint_type,
+    }
+}
+
+// rustc command line options
+pub fn optgroups() -> Vec<getopts::OptGroup> {
+    vec!(
+        optflag("h", "help", "Display this message"),
+        optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
+        optmulti("L", "",   "Add a directory to the library search path", "PATH"),
+        optmulti("", "crate-type", "Comma separated list of types of crates
+                                    for the compiler to emit",
+                 "[bin|lib|rlib|dylib|staticlib]"),
+        optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
+                 "[asm|bc|ir|obj|link]"),
+        optflag("", "crate-id", "Output the crate id and exit"),
+        optflag("", "crate-name", "Output the crate name and exit"),
+        optflag("", "crate-file-name", "Output the file(s) that would be written if compilation \
+              continued and exit"),
+        optflag("g",  "",  "Equivalent to --debuginfo=2"),
+        optopt("",  "debuginfo",  "Emit DWARF debug info to the objects created:
+             0 = no debug info,
+             1 = line-tables only (for stacktraces and breakpoints),
+             2 = full debug info with variable and type information (same as -g)", "LEVEL"),
+        optflag("", "no-trans", "Run all passes except translation; no output"),
+        optflag("", "no-analysis",
+              "Parse and expand the source, but run no analysis and produce no output"),
+        optflag("O", "", "Equivalent to --opt-level=2"),
+        optopt("o", "", "Write output to <filename>", "FILENAME"),
+        optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
+        optopt( "",  "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
+        optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
+        optflagopt("", "pretty",
+                 "Pretty-print the input instead of compiling;
+                  valid types are: normal (un-annotated source),
+                  expanded (crates expanded),
+                  typed (crates expanded, with type annotations),
+                  or identified (fully parenthesized,
+                  AST nodes and blocks with IDs)", "TYPE"),
+        optflagopt("", "dep-info",
+                 "Output dependency info to <filename> after compiling, \
+                  in a format suitable for use by Makefiles", "FILENAME"),
+        optopt("", "sysroot", "Override the system root", "PATH"),
+        optflag("", "test", "Build a test harness"),
+        optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
+                            to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
+                            for details)", "TRIPLE"),
+        optmulti("W", "warn", "Set lint warnings", "OPT"),
+        optmulti("A", "allow", "Set lint allowed", "OPT"),
+        optmulti("D", "deny", "Set lint denied", "OPT"),
+        optmulti("F", "forbid", "Set lint forbidden", "OPT"),
+        optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
+        optmulti("Z", "", "Set internal debugging options", "FLAG"),
+        optflag( "v", "version", "Print version info and exit")
+    )
+}
+
+
+// Convert strings provided as --cfg [cfgspec] into a crate_cfg
+fn parse_cfgspecs(cfgspecs: Vec<~str> ) -> ast::CrateConfig {
+    cfgspecs.move_iter().map(|s| {
+        parse::parse_meta_from_source_str("cfgspec".to_strbuf(),
+                                          s.to_strbuf(),
+                                          Vec::new(),
+                                          &parse::new_parse_sess())
+    }).collect::<ast::CrateConfig>()
+}
+
+pub fn build_session_options(matches: &getopts::Matches) -> Options {
+    let mut crate_types: Vec<CrateType> = Vec::new();
+    let unparsed_crate_types = matches.opt_strs("crate-type");
+    for unparsed_crate_type in unparsed_crate_types.iter() {
+        for part in unparsed_crate_type.split(',') {
+            let new_part = match part {
+                "lib"       => default_lib_output(),
+                "rlib"      => CrateTypeRlib,
+                "staticlib" => CrateTypeStaticlib,
+                "dylib"     => CrateTypeDylib,
+                "bin"       => CrateTypeExecutable,
+                _ => early_error(format!("unknown crate type: `{}`", part))
+            };
+            crate_types.push(new_part)
+        }
+    }
+
+    let parse_only = matches.opt_present("parse-only");
+    let no_trans = matches.opt_present("no-trans");
+    let no_analysis = matches.opt_present("no-analysis");
+
+    let lint_levels = [lint::allow, lint::warn,
+                       lint::deny, lint::forbid];
+    let mut lint_opts = Vec::new();
+    let lint_dict = lint::get_lint_dict();
+    for level in lint_levels.iter() {
+        let level_name = lint::level_to_str(*level);
+
+        let level_short = level_name.slice_chars(0, 1);
+        let level_short = level_short.to_ascii().to_upper().into_str();
+        let flags = matches.opt_strs(level_short).move_iter().collect::<Vec<_>>().append(
+                                   matches.opt_strs(level_name).as_slice());
+        for lint_name in flags.iter() {
+            let lint_name = lint_name.replace("-", "_");
+            match lint_dict.find_equiv(&lint_name) {
+              None => {
+                early_error(format!("unknown {} flag: {}",
+                                    level_name, lint_name));
+              }
+              Some(lint) => {
+                lint_opts.push((lint.lint, *level));
+              }
+            }
+        }
+    }
+
+    let mut debugging_opts = 0;
+    let debug_flags = matches.opt_strs("Z");
+    let debug_map = debugging_opts_map();
+    for debug_flag in debug_flags.iter() {
+        let mut this_bit = 0;
+        for tuple in debug_map.iter() {
+            let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
+            if *name == *debug_flag { this_bit = bit; break; }
+        }
+        if this_bit == 0 {
+            early_error(format!("unknown debug flag: {}", *debug_flag))
+        }
+        debugging_opts |= this_bit;
+    }
+
+    if debugging_opts & DEBUG_LLVM != 0 {
+        unsafe { llvm::LLVMSetDebug(1); }
+    }
+
+    let mut output_types = Vec::new();
+    if !parse_only && !no_trans {
+        let unparsed_output_types = matches.opt_strs("emit");
+        for unparsed_output_type in unparsed_output_types.iter() {
+            for part in unparsed_output_type.split(',') {
+                let output_type = match part.as_slice() {
+                    "asm"  => link::OutputTypeAssembly,
+                    "ir"   => link::OutputTypeLlvmAssembly,
+                    "bc"   => link::OutputTypeBitcode,
+                    "obj"  => link::OutputTypeObject,
+                    "link" => link::OutputTypeExe,
+                    _ => early_error(format!("unknown emission type: `{}`", part))
+                };
+                output_types.push(output_type)
+            }
+        }
+    };
+    output_types.as_mut_slice().sort();
+    output_types.dedup();
+    if output_types.len() == 0 {
+        output_types.push(link::OutputTypeExe);
+    }
+
+    let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
+    let target = matches.opt_str("target").unwrap_or(driver::host_triple().to_owned());
+    let opt_level = {
+        if (debugging_opts & NO_OPT) != 0 {
+            No
+        } else if matches.opt_present("O") {
+            if matches.opt_present("opt-level") {
+                early_error("-O and --opt-level both provided");
+            }
+            Default
+        } else if matches.opt_present("opt-level") {
+            match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) {
+                None      |
+                Some("0") => No,
+                Some("1") => Less,
+                Some("2") => Default,
+                Some("3") => Aggressive,
+                Some(arg) => {
+                    early_error(format!("optimization level needs to be between 0-3 \
+                                        (instead was `{}`)", arg));
+                }
+            }
+        } else {
+            No
+        }
+    };
+    let gc = debugging_opts & GC != 0;
+    let debuginfo = if matches.opt_present("g") {
+        if matches.opt_present("debuginfo") {
+            early_error("-g and --debuginfo both provided");
+        }
+        FullDebugInfo
+    } else if matches.opt_present("debuginfo") {
+        match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) {
+            Some("0") => NoDebugInfo,
+            Some("1") => LimitedDebugInfo,
+            None      |
+            Some("2") => FullDebugInfo,
+            Some(arg) => {
+                early_error(format!("optimization level needs to be between 0-3 \
+                                    (instead was `{}`)", arg));
+            }
+        }
+    } else {
+        NoDebugInfo
+    };
+
+    let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
+        Path::new(s.as_slice())
+    }).collect();
+
+    let cfg = parse_cfgspecs(matches.opt_strs("cfg").move_iter().collect());
+    let test = matches.opt_present("test");
+    let write_dependency_info = (matches.opt_present("dep-info"),
+                                 matches.opt_str("dep-info").map(|p| Path::new(p)));
+
+    let print_metas = (matches.opt_present("crate-id"),
+                       matches.opt_present("crate-name"),
+                       matches.opt_present("crate-file-name"));
+    let cg = build_codegen_options(matches);
+
+    Options {
+        crate_types: crate_types,
+        gc: gc,
+        optimize: opt_level,
+        debuginfo: debuginfo,
+        lint_opts: lint_opts,
+        output_types: output_types,
+        addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
+        maybe_sysroot: sysroot_opt,
+        target_triple: target,
+        cfg: cfg,
+        test: test,
+        parse_only: parse_only,
+        no_trans: no_trans,
+        no_analysis: no_analysis,
+        debugging_opts: debugging_opts,
+        write_dependency_info: write_dependency_info,
+        print_metas: print_metas,
+        cg: cg,
+    }
+}
+
+
+#[cfg(test)]
+mod test {
+
+    use driver::config::{build_configuration, optgroups, build_session_options};
+    use driver::session::build_session;
+
+    use getopts::getopts;
+    use syntax::attr;
+    use syntax::attr::AttrMetaMethods;
+
+    // When the user supplies --test we should implicitly supply --cfg test
+    #[test]
+    fn test_switch_implies_cfg_test() {
+        let matches =
+            &match getopts(["--test".to_owned()], optgroups().as_slice()) {
+              Ok(m) => m,
+              Err(f) => fail!("test_switch_implies_cfg_test: {}", f.to_err_msg())
+            };
+        let sessopts = build_session_options(matches);
+        let sess = build_session(sessopts, None);
+        let cfg = build_configuration(&sess);
+        assert!((attr::contains_name(cfg.as_slice(), "test")));
+    }
+
+    // When the user supplies --test and --cfg test, don't implicitly add
+    // another --cfg test
+    #[test]
+    fn test_switch_implies_cfg_test_unless_cfg_test() {
+        let matches =
+            &match getopts(["--test".to_owned(), "--cfg=test".to_owned()],
+                           optgroups().as_slice()) {
+              Ok(m) => m,
+              Err(f) => {
+                fail!("test_switch_implies_cfg_test_unless_cfg_test: {}",
+                       f.to_err_msg());
+              }
+            };
+        let sessopts = build_session_options(matches);
+        let sess = build_session(sessopts, None);
+        let cfg = build_configuration(&sess);
+        let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
+        assert!(test_items.next().is_some());
+        assert!(test_items.next().is_none());
+    }
+}
index 701117edb478330e9abdacbe5215b2de1d0fc5f2..19f2d33e5b1eb667cac465ef79e8f05d8abba22d 100644 (file)
 
 
 use back::link;
-use back::{arm, x86, x86_64, mips};
-use driver::session::{Aggressive, CrateTypeExecutable, CrateType,
-                      FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
-use driver::session::{Session, No, Less, Default};
-use driver::session;
+use driver::session::Session;
+use driver::config;
 use front;
-use lib::llvm::llvm;
 use lib::llvm::{ContextRef, ModuleRef};
 use metadata::common::LinkMeta;
-use metadata::{creader, filesearch};
-use metadata::cstore::CStore;
+use metadata::creader;
 use metadata::creader::Loader;
-use metadata;
 use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
 use middle::dependency_format;
 use middle;
 use util::common::time;
 use util::ppaux;
-use util::nodemap::{NodeMap, NodeSet};
+use util::nodemap::{NodeSet};
 
 use serialize::{json, Encodable};
 
-use std::cell::{Cell, RefCell};
 use std::io;
 use std::io::fs;
 use std::io::MemReader;
-use std::os;
-use getopts::{optopt, optmulti, optflag, optflagopt};
-use getopts;
 use syntax::ast;
-use syntax::abi;
 use syntax::attr;
 use syntax::attr::{AttrMetaMethods};
-use syntax::codemap;
 use syntax::crateid::CrateId;
-use syntax::diagnostic;
-use syntax::diagnostic::Emitter;
 use syntax::ext::base::CrateLoader;
 use syntax::parse;
-use syntax::parse::token::InternedString;
 use syntax::parse::token;
 use syntax::print::{pp, pprust};
 use syntax;
 
-pub enum PpMode {
-    PpmNormal,
-    PpmExpanded,
-    PpmTyped,
-    PpmIdentified,
-    PpmExpandedIdentified
+pub fn host_triple() -> &'static str {
+    // Get the host triple out of the build environment. This ensures that our
+    // idea of the host triple is the same as for the set of libraries we've
+    // actually built.  We can't just take LLVM's host triple because they
+    // normalize all ix86 architectures to i386.
+    //
+    // Instead of grabbing the host triple (for the current host), we grab (at
+    // compile time) the target triple that this rustc is built with and
+    // calling that (at runtime) the host triple.
+    (option_env!("CFG_COMPILER_HOST_TRIPLE")).
+        expect("CFG_COMPILER_HOST_TRIPLE")
+}
+
+pub fn compile_input(sess: Session,
+                     cfg: ast::CrateConfig,
+                     input: &Input,
+                     outdir: &Option<Path>,
+                     output: &Option<Path>) {
+    // We need nested scopes here, because the intermediate results can keep
+    // large chunks of memory alive and we want to free them as soon as
+    // possible to keep the peak memory usage low
+    let (outputs, trans, sess) = {
+        let (outputs, expanded_crate, ast_map) = {
+            let krate = phase_1_parse_input(&sess, cfg, input);
+            if stop_after_phase_1(&sess) { return; }
+            let outputs = build_output_filenames(input,
+                                                 outdir,
+                                                 output,
+                                                 krate.attrs.as_slice(),
+                                                 &sess);
+            let loader = &mut Loader::new(&sess);
+            let id = link::find_crate_id(krate.attrs.as_slice(),
+                                         outputs.out_filestem);
+            let (expanded_crate, ast_map) = phase_2_configure_and_expand(&sess, loader,
+                                                                         krate, &id);
+            (outputs, expanded_crate, ast_map)
+        };
+        write_out_deps(&sess, input, &outputs, &expanded_crate);
+
+        if stop_after_phase_2(&sess) { return; }
+
+        let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
+        if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
+        let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate,
+                                                     analysis, &outputs);
+
+        // Discard interned strings as they are no longer required.
+        token::get_ident_interner().clear();
+
+        (outputs, trans, tcx.sess)
+    };
+    phase_5_run_llvm_passes(&sess, &trans, &outputs);
+    if stop_after_phase_5(&sess) { return; }
+    phase_6_link_output(&sess, &trans, &outputs);
 }
 
 /**
@@ -78,78 +111,6 @@ pub fn source_name(input: &Input) -> ~str {
     }
 }
 
-pub fn default_configuration(sess: &Session) ->
-   ast::CrateConfig {
-    let tos = match sess.targ_cfg.os {
-        abi::OsWin32 =>   InternedString::new("win32"),
-        abi::OsMacos =>   InternedString::new("macos"),
-        abi::OsLinux =>   InternedString::new("linux"),
-        abi::OsAndroid => InternedString::new("android"),
-        abi::OsFreebsd => InternedString::new("freebsd"),
-    };
-
-    // ARM is bi-endian, however using NDK seems to default
-    // to little-endian unless a flag is provided.
-    let (end,arch,wordsz) = match sess.targ_cfg.arch {
-        abi::X86 =>    ("little", "x86",    "32"),
-        abi::X86_64 => ("little", "x86_64", "64"),
-        abi::Arm =>    ("little", "arm",    "32"),
-        abi::Mips =>   ("big",    "mips",   "32")
-    };
-
-    let fam = match sess.targ_cfg.os {
-        abi::OsWin32 => InternedString::new("windows"),
-        _ => InternedString::new("unix")
-    };
-
-    let mk = attr::mk_name_value_item_str;
-    return vec!(// Target bindings.
-         attr::mk_word_item(fam.clone()),
-         mk(InternedString::new("target_os"), tos),
-         mk(InternedString::new("target_family"), fam),
-         mk(InternedString::new("target_arch"), InternedString::new(arch)),
-         mk(InternedString::new("target_endian"), InternedString::new(end)),
-         mk(InternedString::new("target_word_size"),
-            InternedString::new(wordsz))
-    );
-}
-
-pub fn append_configuration(cfg: &mut ast::CrateConfig,
-                            name: InternedString) {
-    if !cfg.iter().any(|mi| mi.name() == name) {
-        cfg.push(attr::mk_word_item(name))
-    }
-}
-
-pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
-    // Combine the configuration requested by the session (command line) with
-    // some default and generated configuration items
-    let default_cfg = default_configuration(sess);
-    let mut user_cfg = sess.opts.cfg.clone();
-    // If the user wants a test runner, then add the test cfg
-    if sess.opts.test {
-        append_configuration(&mut user_cfg, InternedString::new("test"))
-    }
-    // If the user requested GC, then add the GC cfg
-    append_configuration(&mut user_cfg, if sess.opts.gc {
-        InternedString::new("gc")
-    } else {
-        InternedString::new("nogc")
-    });
-    user_cfg.move_iter().collect::<Vec<_>>().append(default_cfg.as_slice())
-}
-
-// Convert strings provided as --cfg [cfgspec] into a crate_cfg
-fn parse_cfgspecs(cfgspecs: Vec<~str> )
-                  -> ast::CrateConfig {
-    cfgspecs.move_iter().map(|s| {
-        parse::parse_meta_from_source_str("cfgspec".to_strbuf(),
-                                          s.to_strbuf(),
-                                          Vec::new(),
-                                          &parse::new_parse_sess())
-    }).collect::<ast::CrateConfig>()
-}
-
 pub enum Input {
     /// Load source from file
     FileInput(Path),
@@ -183,7 +144,7 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
         }
     });
 
-    if sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0 {
+    if sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0 {
         let mut stdout = io::BufferedWriter::new(io::stdout());
         let mut json = json::PrettyEncoder::new(&mut stdout);
         // unwrapping so IoError isn't ignored
@@ -211,7 +172,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
                                     -> (ast::Crate, syntax::ast_map::Map) {
     let time_passes = sess.time_passes();
 
-    *sess.crate_types.borrow_mut() = session::collect_crate_types(sess, krate.attrs.as_slice());
+    *sess.crate_types.borrow_mut() = collect_crate_types(sess, krate.attrs.as_slice());
 
     time(time_passes, "gated feature checking", (), |_|
          front::feature_gate::check_crate(sess, &krate));
@@ -262,7 +223,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     let (krate, map) = time(time_passes, "assinging node ids and indexing ast", krate, |krate|
          front::assign_node_ids_and_map::assign_node_ids_and_map(sess, krate));
 
-    if sess.opts.debugging_opts & session::AST_JSON != 0 {
+    if sess.opts.debugging_opts & config::AST_JSON != 0 {
         let mut stdout = io::BufferedWriter::new(io::stdout());
         let mut json = json::PrettyEncoder::new(&mut stdout);
         // unwrapping so IoError isn't ignored
@@ -466,7 +427,7 @@ pub fn stop_after_phase_1(sess: &Session) -> bool {
     if sess.show_span() {
         return true;
     }
-    return sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0;
+    return sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0;
 }
 
 pub fn stop_after_phase_2(sess: &Session) -> bool {
@@ -474,7 +435,7 @@ pub fn stop_after_phase_2(sess: &Session) -> bool {
         debug!("invoked with --no-analysis, returning early from compile_input");
         return true;
     }
-    return sess.opts.debugging_opts & session::AST_JSON != 0;
+    return sess.opts.debugging_opts & config::AST_JSON != 0;
 }
 
 pub fn stop_after_phase_5(sess: &Session) -> bool {
@@ -547,46 +508,6 @@ fn write_out_deps(sess: &Session,
     }
 }
 
-pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &Input,
-                     outdir: &Option<Path>, output: &Option<Path>) {
-    // We need nested scopes here, because the intermediate results can keep
-    // large chunks of memory alive and we want to free them as soon as
-    // possible to keep the peak memory usage low
-    let (outputs, trans, sess) = {
-        let (outputs, expanded_crate, ast_map) = {
-            let krate = phase_1_parse_input(&sess, cfg, input);
-            if stop_after_phase_1(&sess) { return; }
-            let outputs = build_output_filenames(input,
-                                                 outdir,
-                                                 output,
-                                                 krate.attrs.as_slice(),
-                                                 &sess);
-            let loader = &mut Loader::new(&sess);
-            let id = link::find_crate_id(krate.attrs.as_slice(),
-                                         outputs.out_filestem);
-            let (expanded_crate, ast_map) = phase_2_configure_and_expand(&sess, loader,
-                                                                         krate, &id);
-            (outputs, expanded_crate, ast_map)
-        };
-        write_out_deps(&sess, input, &outputs, &expanded_crate);
-
-        if stop_after_phase_2(&sess) { return; }
-
-        let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
-        if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
-        let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate,
-                                                     analysis, &outputs);
-
-        // Discard interned strings as they are no longer required.
-        token::get_ident_interner().clear();
-
-        (outputs, trans, tcx.sess)
-    };
-    phase_5_run_llvm_passes(&sess, &trans, &outputs);
-    if stop_after_phase_5(&sess) { return; }
-    phase_6_link_output(&sess, &trans, &outputs);
-}
-
 struct IdentifiedAnnotation;
 
 impl pprust::PpAnn for IdentifiedAnnotation {
@@ -657,7 +578,7 @@ fn post(&self,
 pub fn pretty_print_input(sess: Session,
                           cfg: ast::CrateConfig,
                           input: &Input,
-                          ppm: PpMode,
+                          ppm: ::driver::PpMode,
                           ofile: Option<Path>) {
     let krate = phase_1_parse_input(&sess, cfg, input);
     let id = link::find_crate_id(krate.attrs.as_slice(), input.filestem());
@@ -727,405 +648,60 @@ pub fn pretty_print_input(sess: Session,
 
 }
 
-pub fn get_os(triple: &str) -> Option<abi::Os> {
-    for &(name, os) in os_names.iter() {
-        if triple.contains(name) { return Some(os) }
+pub fn collect_crate_types(session: &Session,
+                           attrs: &[ast::Attribute]) -> Vec<config::CrateType> {
+    // If we're generating a test executable, then ignore all other output
+    // styles at all other locations
+    if session.opts.test {
+        return vec!(config::CrateTypeExecutable)
     }
-    None
-}
-static os_names : &'static [(&'static str, abi::Os)] = &'static [
-    ("mingw32", abi::OsWin32),
-    ("win32",   abi::OsWin32),
-    ("darwin",  abi::OsMacos),
-    ("android", abi::OsAndroid),
-    ("linux",   abi::OsLinux),
-    ("freebsd", abi::OsFreebsd)];
-
-pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
-    for &(arch, abi) in architecture_abis.iter() {
-        if triple.contains(arch) { return Some(abi) }
-    }
-    None
-}
-static architecture_abis : &'static [(&'static str, abi::Architecture)] = &'static [
-    ("i386",   abi::X86),
-    ("i486",   abi::X86),
-    ("i586",   abi::X86),
-    ("i686",   abi::X86),
-    ("i786",   abi::X86),
-
-    ("x86_64", abi::X86_64),
-
-    ("arm",    abi::Arm),
-    ("xscale", abi::Arm),
-    ("thumb",  abi::Arm),
-
-    ("mips",   abi::Mips)];
 
-pub fn build_target_config(sopts: &session::Options) -> session::Config {
-    let os = match get_os(sopts.target_triple) {
-      Some(os) => os,
-      None => early_error("unknown operating system")
-    };
-    let arch = match get_arch(sopts.target_triple) {
-      Some(arch) => arch,
-      None => early_error("unknown architecture: " + sopts.target_triple)
-    };
-    let (int_type, uint_type) = match arch {
-      abi::X86 => (ast::TyI32, ast::TyU32),
-      abi::X86_64 => (ast::TyI64, ast::TyU64),
-      abi::Arm => (ast::TyI32, ast::TyU32),
-      abi::Mips => (ast::TyI32, ast::TyU32)
-    };
-    let target_triple = sopts.target_triple.clone();
-    let target_strs = match arch {
-      abi::X86 => x86::get_target_strs(target_triple, os),
-      abi::X86_64 => x86_64::get_target_strs(target_triple, os),
-      abi::Arm => arm::get_target_strs(target_triple, os),
-      abi::Mips => mips::get_target_strs(target_triple, os)
-    };
-    session::Config {
-        os: os,
-        arch: arch,
-        target_strs: target_strs,
-        int_type: int_type,
-        uint_type: uint_type,
-    }
-}
-
-pub fn host_triple() -> &'static str {
-    // Get the host triple out of the build environment. This ensures that our
-    // idea of the host triple is the same as for the set of libraries we've
-    // actually built.  We can't just take LLVM's host triple because they
-    // normalize all ix86 architectures to i386.
-    //
-    // Instead of grabbing the host triple (for the current host), we grab (at
-    // compile time) the target triple that this rustc is built with and
-    // calling that (at runtime) the host triple.
-    (option_env!("CFG_COMPILER_HOST_TRIPLE")).
-        expect("CFG_COMPILER_HOST_TRIPLE")
-}
-
-pub fn build_session_options(matches: &getopts::Matches) -> session::Options {
-    let mut crate_types: Vec<CrateType> = Vec::new();
-    let unparsed_crate_types = matches.opt_strs("crate-type");
-    for unparsed_crate_type in unparsed_crate_types.iter() {
-        for part in unparsed_crate_type.split(',') {
-            let new_part = match part {
-                "lib"       => session::default_lib_output(),
-                "rlib"      => session::CrateTypeRlib,
-                "staticlib" => session::CrateTypeStaticlib,
-                "dylib"     => session::CrateTypeDylib,
-                "bin"       => session::CrateTypeExecutable,
-                _ => early_error(format!("unknown crate type: `{}`", part))
-            };
-            crate_types.push(new_part)
-        }
-    }
-
-    let parse_only = matches.opt_present("parse-only");
-    let no_trans = matches.opt_present("no-trans");
-    let no_analysis = matches.opt_present("no-analysis");
-
-    let lint_levels = [lint::allow, lint::warn,
-                       lint::deny, lint::forbid];
-    let mut lint_opts = Vec::new();
-    let lint_dict = lint::get_lint_dict();
-    for level in lint_levels.iter() {
-        let level_name = lint::level_to_str(*level);
-
-        let level_short = level_name.slice_chars(0, 1);
-        let level_short = level_short.to_ascii().to_upper().into_str();
-        let flags = matches.opt_strs(level_short).move_iter().collect::<Vec<_>>().append(
-                                   matches.opt_strs(level_name).as_slice());
-        for lint_name in flags.iter() {
-            let lint_name = lint_name.replace("-", "_");
-            match lint_dict.find_equiv(&lint_name) {
-              None => {
-                early_error(format!("unknown {} flag: {}",
-                                    level_name, lint_name));
-              }
-              Some(lint) => {
-                lint_opts.push((lint.lint, *level));
-              }
-            }
-        }
-    }
-
-    let mut debugging_opts = 0;
-    let debug_flags = matches.opt_strs("Z");
-    let debug_map = session::debugging_opts_map();
-    for debug_flag in debug_flags.iter() {
-        let mut this_bit = 0;
-        for tuple in debug_map.iter() {
-            let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
-            if *name == *debug_flag { this_bit = bit; break; }
-        }
-        if this_bit == 0 {
-            early_error(format!("unknown debug flag: {}", *debug_flag))
-        }
-        debugging_opts |= this_bit;
-    }
-
-    if debugging_opts & session::DEBUG_LLVM != 0 {
-        unsafe { llvm::LLVMSetDebug(1); }
-    }
-
-    let mut output_types = Vec::new();
-    if !parse_only && !no_trans {
-        let unparsed_output_types = matches.opt_strs("emit");
-        for unparsed_output_type in unparsed_output_types.iter() {
-            for part in unparsed_output_type.split(',') {
-                let output_type = match part.as_slice() {
-                    "asm"  => link::OutputTypeAssembly,
-                    "ir"   => link::OutputTypeLlvmAssembly,
-                    "bc"   => link::OutputTypeBitcode,
-                    "obj"  => link::OutputTypeObject,
-                    "link" => link::OutputTypeExe,
-                    _ => early_error(format!("unknown emission type: `{}`", part))
-                };
-                output_types.push(output_type)
-            }
-        }
-    };
-    output_types.as_mut_slice().sort();
-    output_types.dedup();
-    if output_types.len() == 0 {
-        output_types.push(link::OutputTypeExe);
-    }
-
-    let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
-    let target = matches.opt_str("target").unwrap_or(host_triple().to_owned());
-    let opt_level = {
-        if (debugging_opts & session::NO_OPT) != 0 {
-            No
-        } else if matches.opt_present("O") {
-            if matches.opt_present("opt-level") {
-                early_error("-O and --opt-level both provided");
-            }
-            Default
-        } else if matches.opt_present("opt-level") {
-            match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) {
-                None      |
-                Some("0") => No,
-                Some("1") => Less,
-                Some("2") => Default,
-                Some("3") => Aggressive,
-                Some(arg) => {
-                    early_error(format!("optimization level needs to be between 0-3 \
-                                        (instead was `{}`)", arg));
-                }
-            }
-        } else {
-            No
-        }
-    };
-    let gc = debugging_opts & session::GC != 0;
-    let debuginfo = if matches.opt_present("g") {
-        if matches.opt_present("debuginfo") {
-            early_error("-g and --debuginfo both provided");
-        }
-        FullDebugInfo
-    } else if matches.opt_present("debuginfo") {
-        match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) {
-            Some("0") => NoDebugInfo,
-            Some("1") => LimitedDebugInfo,
-            None      |
-            Some("2") => FullDebugInfo,
-            Some(arg) => {
-                early_error(format!("optimization level needs to be between 0-3 \
-                                    (instead was `{}`)", arg));
-            }
-        }
+    // Only check command line flags if present. If no types are specified by
+    // command line, then reuse the empty `base` Vec to hold the types that
+    // will be found in crate attributes.
+    let mut base = session.opts.crate_types.clone();
+    if base.len() > 0 {
+        return base
     } else {
-        NoDebugInfo
-    };
-
-    let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
-        Path::new(s.as_slice())
-    }).collect();
-
-    let cfg = parse_cfgspecs(matches.opt_strs("cfg").move_iter().collect());
-    let test = matches.opt_present("test");
-    let write_dependency_info = (matches.opt_present("dep-info"),
-                                 matches.opt_str("dep-info").map(|p| Path::new(p)));
-
-    let print_metas = (matches.opt_present("crate-id"),
-                       matches.opt_present("crate-name"),
-                       matches.opt_present("crate-file-name"));
-    let cg = build_codegen_options(matches);
-
-    session::Options {
-        crate_types: crate_types,
-        gc: gc,
-        optimize: opt_level,
-        debuginfo: debuginfo,
-        lint_opts: lint_opts,
-        output_types: output_types,
-        addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
-        maybe_sysroot: sysroot_opt,
-        target_triple: target,
-        cfg: cfg,
-        test: test,
-        parse_only: parse_only,
-        no_trans: no_trans,
-        no_analysis: no_analysis,
-        debugging_opts: debugging_opts,
-        write_dependency_info: write_dependency_info,
-        print_metas: print_metas,
-        cg: cg,
-    }
-}
-
-pub fn build_codegen_options(matches: &getopts::Matches)
-        -> session::CodegenOptions
-{
-    let mut cg = session::basic_codegen_options();
-    for option in matches.opt_strs("C").move_iter() {
-        let mut iter = option.splitn('=', 1);
-        let key = iter.next().unwrap();
-        let value = iter.next();
-        let option_to_lookup = key.replace("-", "_");
-        let mut found = false;
-        for &(candidate, setter, _) in session::CG_OPTIONS.iter() {
-            if option_to_lookup.as_slice() != candidate { continue }
-            if !setter(&mut cg, value) {
-                match value {
-                    Some(..) => early_error(format!("codegen option `{}` takes \
-                                                     no value", key)),
-                    None => early_error(format!("codegen option `{0}` requires \
-                                                 a value (-C {0}=<value>)",
-                                                key))
+        let iter = attrs.iter().filter_map(|a| {
+            if a.name().equiv(&("crate_type")) {
+                match a.value_str() {
+                    Some(ref n) if n.equiv(&("rlib")) => Some(config::CrateTypeRlib),
+                    Some(ref n) if n.equiv(&("dylib")) => Some(config::CrateTypeDylib),
+                    Some(ref n) if n.equiv(&("lib")) => {
+                        Some(config::default_lib_output())
+                    }
+                    Some(ref n) if n.equiv(&("staticlib")) => {
+                        Some(config::CrateTypeStaticlib)
+                    }
+                    Some(ref n) if n.equiv(&("bin")) => Some(config::CrateTypeExecutable),
+                    Some(_) => {
+                        session.add_lint(lint::UnknownCrateType,
+                                         ast::CRATE_NODE_ID,
+                                         a.span,
+                                         "invalid `crate_type` value".to_owned());
+                        None
+                    }
+                    _ => {
+                        session.add_lint(lint::UnknownCrateType, ast::CRATE_NODE_ID,
+                                        a.span, "`crate_type` requires a value".to_owned());
+                        None
+                    }
                 }
+            } else {
+                None
             }
-            found = true;
-            break;
-        }
-        if !found {
-            early_error(format!("unknown codegen option: `{}`", key));
-        }
-    }
-    return cg;
-}
-
-pub fn build_session(sopts: session::Options,
-                     local_crate_source_file: Option<Path>)
-                     -> Session {
-    let codemap = codemap::CodeMap::new();
-    let diagnostic_handler =
-        diagnostic::default_handler();
-    let span_diagnostic_handler =
-        diagnostic::mk_span_handler(diagnostic_handler, codemap);
-
-    build_session_(sopts, local_crate_source_file, span_diagnostic_handler)
-}
-
-pub fn build_session_(sopts: session::Options,
-                      local_crate_source_file: Option<Path>,
-                      span_diagnostic: diagnostic::SpanHandler)
-                      -> Session {
-    let target_cfg = build_target_config(&sopts);
-    let p_s = parse::new_parse_sess_special_handler(span_diagnostic);
-    let default_sysroot = match sopts.maybe_sysroot {
-        Some(_) => None,
-        None => Some(filesearch::get_or_default_sysroot())
-    };
-
-    // Make the path absolute, if necessary
-    let local_crate_source_file = local_crate_source_file.map(|path|
-        if path.is_absolute() {
-            path.clone()
-        } else {
-            os::getcwd().join(path.clone())
-        }
-    );
-
-    Session {
-        targ_cfg: target_cfg,
-        opts: sopts,
-        cstore: CStore::new(token::get_ident_interner()),
-        parse_sess: p_s,
-        // For a library crate, this is always none
-        entry_fn: RefCell::new(None),
-        entry_type: Cell::new(None),
-        macro_registrar_fn: Cell::new(None),
-        default_sysroot: default_sysroot,
-        local_crate_source_file: local_crate_source_file,
-        working_dir: os::getcwd(),
-        lints: RefCell::new(NodeMap::new()),
-        node_id: Cell::new(1),
-        crate_types: RefCell::new(Vec::new()),
-        features: front::feature_gate::Features::new(),
-        recursion_limit: Cell::new(64),
-    }
-}
-
-pub fn parse_pretty(sess: &Session, name: &str) -> PpMode {
-    match name {
-        "normal" => PpmNormal,
-        "expanded" => PpmExpanded,
-        "typed" => PpmTyped,
-        "expanded,identified" => PpmExpandedIdentified,
-        "identified" => PpmIdentified,
-        _ => {
-            sess.fatal("argument to `pretty` must be one of `normal`, \
-                        `expanded`, `typed`, `identified`, \
-                        or `expanded,identified`");
+        });
+        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<getopts::OptGroup> {
- vec!(
-  optflag("h", "help", "Display this message"),
-  optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
-  optmulti("L", "",   "Add a directory to the library search path", "PATH"),
-  optmulti("", "crate-type", "Comma separated list of types of crates for the compiler to emit",
-           "[bin|lib|rlib|dylib|staticlib]"),
-  optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
-           "[asm|bc|ir|obj|link]"),
-  optflag("", "crate-id", "Output the crate id and exit"),
-  optflag("", "crate-name", "Output the crate name and exit"),
-  optflag("", "crate-file-name", "Output the file(s) that would be written if compilation \
-          continued and exit"),
-  optflag("g",  "",  "Equivalent to --debuginfo=2"),
-  optopt("",  "debuginfo",  "Emit DWARF debug info to the objects created:
-         0 = no debug info,
-         1 = line-tables only (for stacktraces and breakpoints),
-         2 = full debug info with variable and type information (same as -g)", "LEVEL"),
-  optflag("", "no-trans", "Run all passes except translation; no output"),
-  optflag("", "no-analysis",
-          "Parse and expand the source, but run no analysis and produce no output"),
-  optflag("O", "", "Equivalent to --opt-level=2"),
-  optopt("o", "", "Write output to <filename>", "FILENAME"),
-  optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
-  optopt( "",  "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
-  optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
-  optflagopt("", "pretty",
-             "Pretty-print the input instead of compiling;
-              valid types are: normal (un-annotated source),
-              expanded (crates expanded),
-              typed (crates expanded, with type annotations),
-              or identified (fully parenthesized,
-              AST nodes and blocks with IDs)", "TYPE"),
-  optflagopt("", "dep-info",
-             "Output dependency info to <filename> after compiling, \
-              in a format suitable for use by Makefiles", "FILENAME"),
-  optopt("", "sysroot", "Override the system root", "PATH"),
-  optflag("", "test", "Build a test harness"),
-  optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
-                        to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
-                        for details)", "TRIPLE"),
-  optmulti("W", "warn", "Set lint warnings", "OPT"),
-  optmulti("A", "allow", "Set lint allowed", "OPT"),
-  optmulti("D", "deny", "Set lint denied", "OPT"),
-  optmulti("F", "forbid", "Set lint forbidden", "OPT"),
-  optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
-  optmulti("Z", "", "Set internal debugging options", "FLAG"),
-  optflag( "v", "version", "Print version info and exit"))
-}
-
 pub struct OutputFilenames {
     pub 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());
-    }
-}
index 2508e6d8aabc6b192eca0661b87e35014a61d2f2..ec60e2c3e6fcbf7840313bdae5e17c91c31f7af6 100644 (file)
 
 pub use syntax::diagnostic;
 
+use back::link;
+use driver::driver::{Input, FileInput, StrInput};
+use driver::session::{Session, build_session};
+use middle::lint;
+use metadata;
+
+use std::any::AnyRefExt;
+use std::cmp;
+use std::io;
+use std::os;
+use std::str;
+use std::task::TaskBuilder;
+
+use syntax::ast;
+use syntax::parse;
+use syntax::diagnostic::Emitter;
+
+use getopts;
+
+
 pub mod driver;
 pub mod session;
+pub mod config;
+
+
+pub fn main_args(args: &[~str]) -> int {
+    let owned_args = args.to_owned();
+    monitor(proc() run_compiler(owned_args));
+    0
+}
+
+static BUG_REPORT_URL: &'static str =
+    "http://static.rust-lang.org/doc/master/complement-bugreport.html";
+
+fn run_compiler(args: &[~str]) {
+    let matches = match handle_options(Vec::from_slice(args)) {
+        Some(matches) => matches,
+        None => return
+    };
+
+    let (input, input_file_path) = match matches.free.len() {
+        0u => early_error("no input filename given"),
+        1u => {
+            let ifile = matches.free.get(0).as_slice();
+            if ifile == "-" {
+                let contents = io::stdin().read_to_end().unwrap();
+                let src = str::from_utf8(contents.as_slice()).unwrap().to_owned();
+                (StrInput(src), None)
+            } else {
+                (FileInput(Path::new(ifile)), Some(Path::new(ifile)))
+            }
+        }
+        _ => early_error("multiple input filenames provided")
+    };
+
+    let sopts = config::build_session_options(&matches);
+    let sess = build_session(sopts, input_file_path);
+    let cfg = config::build_configuration(&sess);
+    let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
+    let ofile = matches.opt_str("o").map(|o| Path::new(o));
+
+    let pretty = matches.opt_default("pretty", "normal").map(|a| {
+        parse_pretty(&sess, a)
+    });
+    match pretty {
+        Some::<PpMode>(ppm) => {
+            driver::pretty_print_input(sess, cfg, &input, ppm, ofile);
+            return;
+        }
+        None::<PpMode> => {/* continue */ }
+    }
+
+    let r = matches.opt_strs("Z");
+    if r.contains(&("ls".to_owned())) {
+        match input {
+            FileInput(ref ifile) => {
+                let mut stdout = io::stdout();
+                list_metadata(&sess, &(*ifile), &mut stdout).unwrap();
+            }
+            StrInput(_) => {
+                early_error("can not list metadata for stdin");
+            }
+        }
+        return;
+    }
+
+    if print_crate_info(&sess, &input, &odir, &ofile) {
+        return;
+    }
+
+    driver::compile_input(sess, cfg, &input, &odir, &ofile);
+}
+
+pub fn version(argv0: &str) {
+    let vers = match option_env!("CFG_VERSION") {
+        Some(vers) => vers,
+        None => "unknown version"
+    };
+    println!("{} {}", argv0, vers);
+    println!("host: {}", driver::host_triple());
+}
+
+fn usage(argv0: &str) {
+    let message = format!("Usage: {} [OPTIONS] INPUT", argv0);
+    println!("{}\n\
+Additional help:
+    -C help             Print codegen options
+    -W help             Print 'lint' options and default settings
+    -Z help             Print internal options for debugging rustc\n",
+              getopts::usage(message, config::optgroups().as_slice()));
+}
+
+fn describe_warnings() {
+    println!("
+Available lint options:
+    -W <foo>           Warn about <foo>
+    -A <foo>           Allow <foo>
+    -D <foo>           Deny <foo>
+    -F <foo>           Forbid <foo> (deny, and deny all overrides)
+");
+
+    let lint_dict = lint::get_lint_dict();
+    let mut lint_dict = lint_dict.move_iter()
+                                 .map(|(k, v)| (v, k))
+                                 .collect::<Vec<(lint::LintSpec, &'static str)> >();
+    lint_dict.as_mut_slice().sort();
+
+    let mut max_key = 0;
+    for &(_, name) in lint_dict.iter() {
+        max_key = cmp::max(name.len(), max_key);
+    }
+    fn padded(max: uint, s: &str) -> ~str {
+        " ".repeat(max - s.len()) + s
+    }
+    println!("\nAvailable lint checks:\n");
+    println!("    {}  {:7.7s}  {}",
+             padded(max_key, "name"), "default", "meaning");
+    println!("    {}  {:7.7s}  {}\n",
+             padded(max_key, "----"), "-------", "-------");
+    for (spec, name) in lint_dict.move_iter() {
+        let name = name.replace("_", "-");
+        println!("    {}  {:7.7s}  {}",
+                 padded(max_key, name),
+                 lint::level_to_str(spec.default),
+                 spec.desc);
+    }
+    println!("");
+}
+
+fn describe_debug_flags() {
+    println!("\nAvailable debug options:\n");
+    let r = config::debugging_opts_map();
+    for tuple in r.iter() {
+        match *tuple {
+            (ref name, ref desc, _) => {
+                println!("    -Z {:>20s} -- {}", *name, *desc);
+            }
+        }
+    }
+}
+
+fn describe_codegen_flags() {
+    println!("\nAvailable codegen options:\n");
+    let mut cg = config::basic_codegen_options();
+    for &(name, parser, desc) in config::CG_OPTIONS.iter() {
+        // we invoke the parser function on `None` to see if this option needs
+        // an argument or not.
+        let (width, extra) = if parser(&mut cg, None) {
+            (25, "")
+        } else {
+            (21, "=val")
+        };
+        println!("    -C {:>width$s}{} -- {}", name.replace("_", "-"),
+                 extra, desc, width=width);
+    }
+}
+
+/// Process command line options. Emits messages as appropirate.If compilation
+/// should continue, returns a getopts::Matches object parsed from args, otherwise
+/// returns None.
+pub fn handle_options(mut args: Vec<~str>) -> Option<getopts::Matches> {
+    let binary = args.shift().unwrap();
+
+    if args.is_empty() { usage(binary); return None; }
+
+    let matches =
+        match getopts::getopts(args.as_slice(), config::optgroups().as_slice()) {
+            Ok(m) => m,
+            Err(f) => {
+                early_error(f.to_err_msg());
+            }
+        };
+
+    if matches.opt_present("h") || matches.opt_present("help") {
+        usage(binary);
+        return None;
+    }
+
+    let lint_flags = matches.opt_strs("W").move_iter().collect::<Vec<_>>().append(
+                                    matches.opt_strs("warn").as_slice());
+    if lint_flags.iter().any(|x| x == &"help".to_owned()) {
+        describe_warnings();
+        return None;
+    }
+
+    let r = matches.opt_strs("Z");
+    if r.iter().any(|x| x == &"help".to_owned()) {
+        describe_debug_flags();
+        return None;
+    }
+
+    let cg_flags = matches.opt_strs("C");
+    if cg_flags.iter().any(|x| x == &"help".to_owned()) {
+        describe_codegen_flags();
+        return None;
+    }
+
+    if cg_flags.contains(&"passes=list".to_owned()) {
+        unsafe { ::lib::llvm::llvm::LLVMRustPrintPasses(); }
+        return None;
+    }
+
+    if matches.opt_present("v") || matches.opt_present("version") {
+        version(binary);
+        return None;
+    }
+
+    Some(matches)
+}
+
+fn print_crate_info(sess: &Session,
+                    input: &Input,
+                    odir: &Option<Path>,
+                    ofile: &Option<Path>)
+                    -> bool {
+    let (crate_id, crate_name, crate_file_name) = sess.opts.print_metas;
+    // these nasty nested conditions are to avoid doing extra work
+    if crate_id || crate_name || crate_file_name {
+        let attrs = parse_crate_attrs(sess, input);
+        let t_outputs = driver::build_output_filenames(input, odir, ofile,
+                                                       attrs.as_slice(), sess);
+        let id = link::find_crate_id(attrs.as_slice(), t_outputs.out_filestem);
+
+        if crate_id {
+            println!("{}", id.to_str());
+        }
+        if crate_name {
+            println!("{}", id.name);
+        }
+        if crate_file_name {
+            let crate_types = driver::collect_crate_types(sess, attrs.as_slice());
+            for &style in crate_types.iter() {
+                let fname = link::filename_for_input(sess, style, &id,
+                                                     &t_outputs.with_extension(""));
+                println!("{}", fname.filename_display());
+            }
+        }
+
+        true
+    } else {
+        false
+    }
+}
+
+pub enum PpMode {
+    PpmNormal,
+    PpmExpanded,
+    PpmTyped,
+    PpmIdentified,
+    PpmExpandedIdentified
+}
+
+pub fn parse_pretty(sess: &Session, name: &str) -> PpMode {
+    match name {
+        "normal" => PpmNormal,
+        "expanded" => PpmExpanded,
+        "typed" => PpmTyped,
+        "expanded,identified" => PpmExpandedIdentified,
+        "identified" => PpmIdentified,
+        _ => {
+            sess.fatal("argument to `pretty` must be one of `normal`, \
+                        `expanded`, `typed`, `identified`, \
+                        or `expanded,identified`");
+        }
+    }
+}
+
+fn parse_crate_attrs(sess: &Session, input: &Input) ->
+                     Vec<ast::Attribute> {
+    let result = match *input {
+        FileInput(ref ifile) => {
+            parse::parse_crate_attrs_from_file(ifile,
+                                               Vec::new(),
+                                               &sess.parse_sess)
+        }
+        StrInput(ref src) => {
+            parse::parse_crate_attrs_from_source_str(
+                driver::anon_src().to_strbuf(),
+                src.to_strbuf(),
+                Vec::new(),
+                &sess.parse_sess)
+        }
+    };
+    result.move_iter().collect()
+}
+
+pub fn early_error(msg: &str) -> ! {
+    let mut emitter = diagnostic::EmitterWriter::stderr();
+    emitter.emit(None, msg, diagnostic::Fatal);
+    fail!(diagnostic::FatalError);
+}
+
+pub fn list_metadata(sess: &Session, path: &Path,
+                     out: &mut io::Writer) -> io::IoResult<()> {
+    metadata::loader::list_file_metadata(
+        config::cfg_os_to_meta_os(sess.targ_cfg.os), path, out)
+}
+
+/// Run a procedure which will detect failures in the compiler and print nicer
+/// error messages rather than just failing the test.
+///
+/// The diagnostic emitter yielded to the procedure should be used for reporting
+/// errors of the compiler.
+fn monitor(f: proc():Send) {
+    // FIXME: This is a hack for newsched since it doesn't support split stacks.
+    // rustc needs a lot of stack! When optimizations are disabled, it needs
+    // even *more* stack than usual as well.
+    #[cfg(rtopt)]
+    static STACK_SIZE: uint = 6000000;  // 6MB
+    #[cfg(not(rtopt))]
+    static STACK_SIZE: uint = 20000000; // 20MB
+
+    let mut task_builder = TaskBuilder::new().named("rustc");
+
+    // FIXME: Hacks on hacks. If the env is trying to override the stack size
+    // then *don't* set it explicitly.
+    if os::getenv("RUST_MIN_STACK").is_none() {
+        task_builder.opts.stack_size = Some(STACK_SIZE);
+    }
+
+    let (tx, rx) = channel();
+    let w = io::ChanWriter::new(tx);
+    let mut r = io::ChanReader::new(rx);
+
+    match task_builder.try(proc() {
+        io::stdio::set_stderr(box w);
+        f()
+    }) {
+        Ok(()) => { /* fallthrough */ }
+        Err(value) => {
+            // Task failed without emitting a fatal diagnostic
+            if !value.is::<diagnostic::FatalError>() {
+                let mut emitter = diagnostic::EmitterWriter::stderr();
+
+                // a .span_bug or .bug call has already printed what
+                // it wants to print.
+                if !value.is::<diagnostic::ExplicitBug>() {
+                    emitter.emit(
+                        None,
+                        "unexpected failure",
+                        diagnostic::Bug);
+                }
+
+                let xs = [
+                    "the compiler hit an unexpected failure path. this is a bug.".to_owned(),
+                    "we would appreciate a bug report: " + BUG_REPORT_URL,
+                    "run with `RUST_BACKTRACE=1` for a backtrace".to_owned(),
+                ];
+                for note in xs.iter() {
+                    emitter.emit(None, *note, diagnostic::Note)
+                }
+
+                match r.read_to_str() {
+                    Ok(s) => println!("{}", s),
+                    Err(e) => emitter.emit(None,
+                                           format!("failed to read internal stderr: {}", e),
+                                           diagnostic::Error),
+                }
+            }
+
+            // Fail so the process returns a failure code, but don't pollute the
+            // output with some unnecessary failure messages, we've already
+            // printed everything that we needed to.
+            io::stdio::set_stderr(box io::util::NullWriter);
+            fail!();
+        }
+    }
+}
index 859647b1beb47c7d8bcf827351450cdc52489d6b..24921efdb782e7c876a07fbcd6f48fbf96e29b3d 100644 (file)
 // except according to those terms.
 
 
-use back::target_strs;
-use back;
-use driver::driver::host_triple;
+use driver::config;
+use driver::driver;
 use front;
+use metadata::cstore::CStore;
 use metadata::filesearch;
-use metadata;
 use middle::lint;
 use util::nodemap::NodeMap;
 
-use syntax::attr::AttrMetaMethods;
 use syntax::ast::NodeId;
-use syntax::ast::{IntTy, UintTy};
 use syntax::codemap::Span;
 use syntax::diagnostic;
+use syntax::parse;
+use syntax::parse::token;
 use syntax::parse::ParseSess;
-use syntax::{abi, ast, codemap};
+use syntax::{ast, codemap};
 
+use std::os;
 use std::cell::{Cell, RefCell};
-use collections::HashSet;
 
-pub struct Config {
-    pub os: abi::Os,
-    pub arch: abi::Architecture,
-    pub target_strs: target_strs::t,
-    pub int_type: IntTy,
-    pub uint_type: UintTy,
-}
-
-macro_rules! debugging_opts(
-    ([ $opt:ident ] $cnt:expr ) => (
-        pub static $opt: u64 = 1 << $cnt;
-    );
-    ([ $opt:ident, $($rest:ident),* ] $cnt:expr ) => (
-        pub static $opt: u64 = 1 << $cnt;
-        debugging_opts!([ $($rest),* ] $cnt + 1)
-    )
-)
-
-debugging_opts!(
-    [
-        VERBOSE,
-        TIME_PASSES,
-        COUNT_LLVM_INSNS,
-        TIME_LLVM_PASSES,
-        TRANS_STATS,
-        ASM_COMMENTS,
-        NO_VERIFY,
-        BORROWCK_STATS,
-        NO_LANDING_PADS,
-        DEBUG_LLVM,
-        SHOW_SPAN,
-        COUNT_TYPE_SIZES,
-        META_STATS,
-        NO_OPT,
-        GC,
-        PRINT_LINK_ARGS,
-        PRINT_LLVM_PASSES,
-        LTO,
-        AST_JSON,
-        AST_JSON_NOEXPAND,
-        LS
-    ]
-    0
-)
-
-pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
-    vec!(("verbose", "in general, enable more debug printouts", VERBOSE),
-     ("time-passes", "measure time of each rustc pass", TIME_PASSES),
-     ("count-llvm-insns", "count where LLVM \
-                           instrs originate", COUNT_LLVM_INSNS),
-     ("time-llvm-passes", "measure time of each LLVM pass",
-      TIME_LLVM_PASSES),
-     ("trans-stats", "gather trans statistics", TRANS_STATS),
-     ("asm-comments", "generate comments into the assembly (may change behavior)",
-      ASM_COMMENTS),
-     ("no-verify", "skip LLVM verification", NO_VERIFY),
-     ("borrowck-stats", "gather borrowck statistics",  BORROWCK_STATS),
-     ("no-landing-pads", "omit landing pads for unwinding",
-      NO_LANDING_PADS),
-     ("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM),
-     ("show-span", "show spans for compiler debugging", SHOW_SPAN),
-     ("count-type-sizes", "count the sizes of aggregate types",
-      COUNT_TYPE_SIZES),
-     ("meta-stats", "gather metadata statistics", META_STATS),
-     ("no-opt", "do not optimize, even if -O is passed", NO_OPT),
-     ("print-link-args", "Print the arguments passed to the linker",
-      PRINT_LINK_ARGS),
-     ("gc", "Garbage collect shared data (experimental)", GC),
-     ("print-llvm-passes",
-      "Prints the llvm optimization passes being run",
-      PRINT_LLVM_PASSES),
-     ("lto", "Perform LLVM link-time optimizations", LTO),
-     ("ast-json", "Print the AST as JSON and halt", AST_JSON),
-     ("ast-json-noexpand", "Print the pre-expansion AST as JSON and halt", AST_JSON_NOEXPAND),
-     ("ls", "List the symbols defined by a library crate", LS))
-}
-
-#[deriving(Clone, Eq)]
-pub enum OptLevel {
-    No, // -O0
-    Less, // -O1
-    Default, // -O2
-    Aggressive // -O3
-}
-
-#[deriving(Clone, Eq)]
-pub enum DebugInfoLevel {
-    NoDebugInfo,
-    LimitedDebugInfo,
-    FullDebugInfo,
-}
-
-#[deriving(Clone)]
-pub struct Options {
-    // The crate config requested for the session, which may be combined
-    // with additional crate configurations during the compile process
-    pub crate_types: Vec<CrateType>,
-
-    pub gc: bool,
-    pub optimize: OptLevel,
-    pub debuginfo: DebugInfoLevel,
-    pub lint_opts: Vec<(lint::Lint, lint::level)> ,
-    pub output_types: Vec<back::link::OutputType> ,
-    // This was mutable for rustpkg, which updates search paths based on the
-    // parsed code. It remains mutable in case its replacements wants to use
-    // this.
-    pub addl_lib_search_paths: RefCell<HashSet<Path>>,
-    pub maybe_sysroot: Option<Path>,
-    pub target_triple: ~str,
-    // User-specified cfg meta items. The compiler itself will add additional
-    // items to the crate config, and during parsing the entire crate config
-    // will be added to the crate AST node.  This should not be used for
-    // anything except building the full crate config prior to parsing.
-    pub cfg: ast::CrateConfig,
-    pub test: bool,
-    pub parse_only: bool,
-    pub no_trans: bool,
-    pub no_analysis: bool,
-    pub debugging_opts: u64,
-    /// Whether to write dependency files. It's (enabled, optional filename).
-    pub write_dependency_info: (bool, Option<Path>),
-    /// Crate id-related things to maybe print. It's (crate_id, crate_name, crate_file_name).
-    pub print_metas: (bool, bool, bool),
-    pub cg: CodegenOptions,
-}
-
-// The type of entry function, so
-// users can have their own entry
-// functions that don't start a
-// scheduler
-#[deriving(Eq)]
-pub enum EntryFnType {
-    EntryMain,
-    EntryStart,
-    EntryNone,
-}
-
-#[deriving(Eq, Ord, Clone, TotalOrd, TotalEq, Hash)]
-pub enum CrateType {
-    CrateTypeExecutable,
-    CrateTypeDylib,
-    CrateTypeRlib,
-    CrateTypeStaticlib,
-}
 
 pub struct Session {
-    pub targ_cfg: Config,
-    pub opts: Options,
-    pub cstore: metadata::cstore::CStore,
+    pub targ_cfg: config::Config,
+    pub opts: config::Options,
+    pub cstore: CStore,
     pub parse_sess: ParseSess,
     // For a library crate, this is always none
     pub entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
-    pub entry_type: Cell<Option<EntryFnType>>,
+    pub entry_type: Cell<Option<config::EntryFnType>>,
     pub macro_registrar_fn: Cell<Option<ast::NodeId>>,
     pub default_sysroot: Option<Path>,
     // The name of the root source file of the crate, in the local file system. The path is always
@@ -190,7 +45,7 @@ pub struct Session {
     pub working_dir: Path,
     pub lints: RefCell<NodeMap<Vec<(lint::Lint, codemap::Span, ~str)>>>,
     pub node_id: Cell<ast::NodeId>,
-    pub crate_types: RefCell<Vec<CrateType>>,
+    pub crate_types: RefCell<Vec<config::CrateType>>,
     pub features: front::feature_gate::Features,
 
     /// The maximum recursion limit for potentially infinitely recursive
@@ -289,33 +144,33 @@ pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {
     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 @@ pub fn target_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
     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<Path>)
+                     -> 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<Path>,
+                      span_diagnostic: diagnostic::SpanHandler)
+                      -> Session {
+    let target_cfg = config::build_target_config(&sopts);
+    let p_s = parse::new_parse_sess_special_handler(span_diagnostic);
+    let default_sysroot = match sopts.maybe_sysroot {
+        Some(_) => None,
+        None => Some(filesearch::get_or_default_sysroot())
+    };
+
+    // Make the path absolute, if necessary
+    let local_crate_source_file = local_crate_source_file.map(|path|
+        if path.is_absolute() {
+            path.clone()
+        } else {
+            os::getcwd().join(path.clone())
         }
+    );
 
+    Session {
+        targ_cfg: target_cfg,
+        opts: sopts,
+        cstore: CStore::new(token::get_ident_interner()),
+        parse_sess: p_s,
+        // For a library crate, this is always none
+        entry_fn: RefCell::new(None),
+        entry_type: Cell::new(None),
+        macro_registrar_fn: Cell::new(None),
+        default_sysroot: default_sysroot,
+        local_crate_source_file: local_crate_source_file,
+        working_dir: os::getcwd(),
+        lints: RefCell::new(NodeMap::new()),
+        node_id: Cell::new(1),
+        crate_types: RefCell::new(Vec::new()),
+        features: front::feature_gate::Features::new(),
+        recursion_limit: Cell::new(64),
     }
-) )
+}
 
-cgoptions!(
-    ar: Option<~str> = (None, parse_opt_string,
-        "tool to assemble archives with"),
-    linker: Option<~str> = (None, parse_opt_string,
-        "system linker to link outputs with"),
-    link_args: Vec<~str> = (Vec::new(), parse_list,
-        "extra arguments to pass to the linker (space separated)"),
-    target_cpu: ~str = ("generic".to_owned(), parse_string,
-        "select target processor (llc -mcpu=help for details)"),
-    target_feature: ~str = ("".to_owned(), parse_string,
-        "target specific attributes (llc -mattr=help for details)"),
-    passes: Vec<~str> = (Vec::new(), parse_list,
-        "a list of extra LLVM passes to run (space separated)"),
-    llvm_args: Vec<~str> = (Vec::new(), parse_list,
-        "a list of arguments to pass to llvm (space separated)"),
-    save_temps: bool = (false, parse_bool,
-        "save all temporary output files during compilation"),
-    android_cross_path: Option<~str> = (None, parse_opt_string,
-        "the path to the Android NDK"),
-    no_rpath: bool = (false, parse_bool,
-        "disables setting the rpath in libs/exes"),
-    no_prepopulate_passes: bool = (false, parse_bool,
-        "don't pre-populate the pass manager with a list of passes"),
-    no_vectorize_loops: bool = (false, parse_bool,
-        "don't run the loop vectorization optimization passes"),
-    no_vectorize_slp: bool = (false, parse_bool,
-        "don't run LLVM's SLP vectorization pass"),
-    soft_float: bool = (false, parse_bool,
-        "generate software floating point library calls"),
-    prefer_dynamic: bool = (false, parse_bool,
-        "prefer dynamic linking to static linking"),
-    no_integrated_as: bool = (false, parse_bool,
-        "use an external assembler rather than LLVM's integrated one"),
-    relocation_model: ~str = ("pic".to_owned(), parse_string,
-         "choose the relocation model to use (llc -relocation-model for details)"),
-)
 
 // Seems out of place, but it uses session, so I'm putting it here
 pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> StrBuf)
@@ -476,72 +252,3 @@ pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> StrBuf)
     diagnostic::expect(sess.diagnostic(), opt, msg)
 }
 
-pub fn default_lib_output() -> CrateType {
-    CrateTypeRlib
-}
-
-pub fn collect_crate_types(session: &Session,
-                           attrs: &[ast::Attribute]) -> Vec<CrateType> {
-    // If we're generating a test executable, then ignore all other output
-    // styles at all other locations
-    if session.opts.test {
-        return vec!(CrateTypeExecutable)
-    }
-
-    // Only check command line flags if present. If no types are specified by
-    // command line, then reuse the empty `base` Vec to hold the types that
-    // will be found in crate attributes.
-    let mut base = session.opts.crate_types.clone();
-    if base.len() > 0 {
-        return base
-    } else {
-        let iter = attrs.iter().filter_map(|a| {
-            if a.name().equiv(&("crate_type")) {
-                match a.value_str() {
-                    Some(ref n) if n.equiv(&("rlib")) => Some(CrateTypeRlib),
-                    Some(ref n) if n.equiv(&("dylib")) => Some(CrateTypeDylib),
-                    Some(ref n) if n.equiv(&("lib")) => {
-                        Some(default_lib_output())
-                    }
-                    Some(ref n) if n.equiv(&("staticlib")) => {
-                        Some(CrateTypeStaticlib)
-                    }
-                    Some(ref n) if n.equiv(&("bin")) => Some(CrateTypeExecutable),
-                    Some(_) => {
-                        session.add_lint(lint::UnknownCrateType,
-                                         ast::CRATE_NODE_ID,
-                                         a.span,
-                                         "invalid `crate_type` value".to_owned());
-                        None
-                    }
-                    _ => {
-                        session.add_lint(lint::UnknownCrateType, ast::CRATE_NODE_ID,
-                                        a.span, "`crate_type` requires a value".to_owned());
-                        None
-                    }
-                }
-            } else {
-                None
-            }
-        });
-        base.extend(iter);
-        if base.len() == 0 {
-            base.push(CrateTypeExecutable);
-        }
-        base.as_mut_slice().sort();
-        base.dedup();
-        return base;
-    }
-}
-
-pub fn sess_os_to_meta_os(os: abi::Os) -> metadata::loader::Os {
-    use metadata::loader;
-
-    match os {
-        abi::OsWin32 => loader::OsWin32,
-        abi::OsLinux => loader::OsLinux,
-        abi::OsAndroid => loader::OsAndroid,
-        abi::OsMacos => loader::OsMacos,
-        abi::OsFreebsd => loader::OsFreebsd
-    }
-}
index 959197e5b2b02df5be07d8182bc9111ae9fa80ba..da1f7bce89bc98b71184cbb6351779b82a6053ce 100644 (file)
@@ -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 @@ fn fold_crate(&mut self, krate: ast::Crate) -> ast::Crate {
         });
 
         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 {
index 0962acd0a2ebf23acf34db153c955d69e708e15e..5b5ec2cdc2157c10458379efff542e4ed0d6f443 100644 (file)
 #[phase(syntax, link)]
 extern crate log;
 
-use back::link;
-use driver::session;
-use middle::lint;
-
-use d = driver::driver;
-
-use std::any::AnyRefExt;
-use std::cmp;
-use std::io;
-use std::os;
-use std::str;
-use std::task::TaskBuilder;
-use syntax::ast;
-use syntax::diagnostic::Emitter;
-use syntax::diagnostic;
-use syntax::parse;
-
 pub mod middle {
     pub mod trans;
     pub mod ty;
@@ -136,309 +119,8 @@ pub mod lib {
     pub mod llvmdeps;
 }
 
-static BUG_REPORT_URL: &'static str =
-    "http://static.rust-lang.org/doc/master/complement-bugreport.html";
-
-pub fn version(argv0: &str) {
-    let vers = match option_env!("CFG_VERSION") {
-        Some(vers) => vers,
-        None => "unknown version"
-    };
-    println!("{} {}", argv0, vers);
-    println!("host: {}", d::host_triple());
-}
-
-pub fn usage(argv0: &str) {
-    let message = format!("Usage: {} [OPTIONS] INPUT", argv0);
-    println!("{}\n\
-Additional help:
-    -C help             Print codegen options
-    -W help             Print 'lint' options and default settings
-    -Z help             Print internal options for debugging rustc\n",
-              getopts::usage(message, d::optgroups().as_slice()));
-}
-
-pub fn describe_warnings() {
-    println!("
-Available lint options:
-    -W <foo>           Warn about <foo>
-    -A <foo>           Allow <foo>
-    -D <foo>           Deny <foo>
-    -F <foo>           Forbid <foo> (deny, and deny all overrides)
-");
-
-    let lint_dict = lint::get_lint_dict();
-    let mut lint_dict = lint_dict.move_iter()
-                                 .map(|(k, v)| (v, k))
-                                 .collect::<Vec<(lint::LintSpec, &'static str)> >();
-    lint_dict.as_mut_slice().sort();
-
-    let mut max_key = 0;
-    for &(_, name) in lint_dict.iter() {
-        max_key = cmp::max(name.len(), max_key);
-    }
-    fn padded(max: uint, s: &str) -> ~str {
-        " ".repeat(max - s.len()) + s
-    }
-    println!("\nAvailable lint checks:\n");
-    println!("    {}  {:7.7s}  {}",
-             padded(max_key, "name"), "default", "meaning");
-    println!("    {}  {:7.7s}  {}\n",
-             padded(max_key, "----"), "-------", "-------");
-    for (spec, name) in lint_dict.move_iter() {
-        let name = name.replace("_", "-");
-        println!("    {}  {:7.7s}  {}",
-                 padded(max_key, name),
-                 lint::level_to_str(spec.default),
-                 spec.desc);
-    }
-    println!("");
-}
-
-pub fn describe_debug_flags() {
-    println!("\nAvailable debug options:\n");
-    let r = session::debugging_opts_map();
-    for tuple in r.iter() {
-        match *tuple {
-            (ref name, ref desc, _) => {
-                println!("    -Z {:>20s} -- {}", *name, *desc);
-            }
-        }
-    }
-}
-
-pub fn describe_codegen_flags() {
-    println!("\nAvailable codegen options:\n");
-    let mut cg = session::basic_codegen_options();
-    for &(name, parser, desc) in session::CG_OPTIONS.iter() {
-        // we invoke the parser function on `None` to see if this option needs
-        // an argument or not.
-        let (width, extra) = if parser(&mut cg, None) {
-            (25, "")
-        } else {
-            (21, "=val")
-        };
-        println!("    -C {:>width$s}{} -- {}", name.replace("_", "-"),
-                 extra, desc, width=width);
-    }
-}
-
-pub fn run_compiler(args: &[~str]) {
-    let mut args = Vec::from_slice(args);
-    let binary = args.shift().unwrap();
-
-    if args.is_empty() { usage(binary); return; }
-
-    let matches =
-        &match getopts::getopts(args.as_slice(), d::optgroups().as_slice()) {
-          Ok(m) => m,
-          Err(f) => {
-            d::early_error(f.to_err_msg());
-          }
-        };
-
-    if matches.opt_present("h") || matches.opt_present("help") {
-        usage(binary);
-        return;
-    }
-
-    let lint_flags = matches.opt_strs("W").move_iter().collect::<Vec<_>>().append(
-                                    matches.opt_strs("warn").as_slice());
-    if lint_flags.iter().any(|x| x == &"help".to_owned()) {
-        describe_warnings();
-        return;
-    }
-
-    let r = matches.opt_strs("Z");
-    if r.iter().any(|x| x == &"help".to_owned()) {
-        describe_debug_flags();
-        return;
-    }
-
-    let cg_flags = matches.opt_strs("C");
-    if cg_flags.iter().any(|x| x == &"help".to_owned()) {
-        describe_codegen_flags();
-        return;
-    }
-
-    if cg_flags.contains(&"passes=list".to_owned()) {
-        unsafe { lib::llvm::llvm::LLVMRustPrintPasses(); }
-        return;
-    }
-
-    if matches.opt_present("v") || matches.opt_present("version") {
-        version(binary);
-        return;
-    }
-    let (input, input_file_path) = match matches.free.len() {
-      0u => d::early_error("no input filename given"),
-      1u => {
-        let ifile = matches.free.get(0).as_slice();
-        if ifile == "-" {
-            let contents = io::stdin().read_to_end().unwrap();
-            let src = str::from_utf8(contents.as_slice()).unwrap().to_owned();
-            (d::StrInput(src), None)
-        } else {
-            (d::FileInput(Path::new(ifile)), Some(Path::new(ifile)))
-        }
-      }
-      _ => d::early_error("multiple input filenames provided")
-    };
-
-    let sopts = d::build_session_options(matches);
-    let sess = d::build_session(sopts, input_file_path);
-    let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
-    let ofile = matches.opt_str("o").map(|o| Path::new(o));
-    let cfg = d::build_configuration(&sess);
-    let pretty = matches.opt_default("pretty", "normal").map(|a| {
-        d::parse_pretty(&sess, a)
-    });
-    match pretty {
-        Some::<d::PpMode>(ppm) => {
-            d::pretty_print_input(sess, cfg, &input, ppm, ofile);
-            return;
-        }
-        None::<d::PpMode> => {/* continue */ }
-    }
-
-    if r.contains(&("ls".to_owned())) {
-        match input {
-            d::FileInput(ref ifile) => {
-                let mut stdout = io::stdout();
-                d::list_metadata(&sess, &(*ifile), &mut stdout).unwrap();
-            }
-            d::StrInput(_) => {
-                d::early_error("can not list metadata for stdin");
-            }
-        }
-        return;
-    }
-    let (crate_id, crate_name, crate_file_name) = sess.opts.print_metas;
-    // these nasty nested conditions are to avoid doing extra work
-    if crate_id || crate_name || crate_file_name {
-        let attrs = parse_crate_attrs(&sess, &input);
-        let t_outputs = d::build_output_filenames(&input, &odir, &ofile,
-                                                  attrs.as_slice(), &sess);
-        let id = link::find_crate_id(attrs.as_slice(), t_outputs.out_filestem);
-
-        if crate_id {
-            println!("{}", id.to_str());
-        }
-        if crate_name {
-            println!("{}", id.name);
-        }
-        if crate_file_name {
-            let crate_types = session::collect_crate_types(&sess,
-                                                           attrs.as_slice());
-            for &style in crate_types.iter() {
-                let fname = link::filename_for_input(&sess, style, &id,
-                                                     &t_outputs.with_extension(""));
-                println!("{}", fname.filename_display());
-            }
-        }
-
-        return;
-    }
-
-    d::compile_input(sess, cfg, &input, &odir, &ofile);
-}
-
-fn parse_crate_attrs(sess: &session::Session, input: &d::Input) ->
-                     Vec<ast::Attribute> {
-    let result = match *input {
-        d::FileInput(ref ifile) => {
-            parse::parse_crate_attrs_from_file(ifile,
-                                               Vec::new(),
-                                               &sess.parse_sess)
-        }
-        d::StrInput(ref src) => {
-            parse::parse_crate_attrs_from_source_str(
-                d::anon_src().to_strbuf(),
-                src.to_strbuf(),
-                Vec::new(),
-                &sess.parse_sess)
-        }
-    };
-    result.move_iter().collect()
-}
-
-/// Run a procedure which will detect failures in the compiler and print nicer
-/// error messages rather than just failing the test.
-///
-/// The diagnostic emitter yielded to the procedure should be used for reporting
-/// errors of the compiler.
-pub fn monitor(f: proc():Send) {
-    // FIXME: This is a hack for newsched since it doesn't support split stacks.
-    // rustc needs a lot of stack! When optimizations are disabled, it needs
-    // even *more* stack than usual as well.
-    #[cfg(rtopt)]
-    static STACK_SIZE: uint = 6000000;  // 6MB
-    #[cfg(not(rtopt))]
-    static STACK_SIZE: uint = 20000000; // 20MB
-
-    let mut task_builder = TaskBuilder::new().named("rustc");
-
-    // FIXME: Hacks on hacks. If the env is trying to override the stack size
-    // then *don't* set it explicitly.
-    if os::getenv("RUST_MIN_STACK").is_none() {
-        task_builder.opts.stack_size = Some(STACK_SIZE);
-    }
-
-    let (tx, rx) = channel();
-    let w = io::ChanWriter::new(tx);
-    let mut r = io::ChanReader::new(rx);
-
-    match task_builder.try(proc() {
-        io::stdio::set_stderr(box w);
-        f()
-    }) {
-        Ok(()) => { /* fallthrough */ }
-        Err(value) => {
-            // Task failed without emitting a fatal diagnostic
-            if !value.is::<diagnostic::FatalError>() {
-                let mut emitter = diagnostic::EmitterWriter::stderr();
-
-                // a .span_bug or .bug call has already printed what
-                // it wants to print.
-                if !value.is::<diagnostic::ExplicitBug>() {
-                    emitter.emit(
-                        None,
-                        "unexpected failure",
-                        diagnostic::Bug);
-                }
-
-                let xs = [
-                    "the compiler hit an unexpected failure path. this is a bug.".to_owned(),
-                    "we would appreciate a bug report: " + BUG_REPORT_URL,
-                    "run with `RUST_BACKTRACE=1` for a backtrace".to_owned(),
-                ];
-                for note in xs.iter() {
-                    emitter.emit(None, *note, diagnostic::Note)
-                }
-
-                match r.read_to_str() {
-                    Ok(s) => println!("{}", s),
-                    Err(e) => emitter.emit(None,
-                                           format!("failed to read internal stderr: {}", e),
-                                           diagnostic::Error),
-                }
-            }
-
-            // Fail so the process returns a failure code, but don't pollute the
-            // output with some unnecessary failure messages, we've already
-            // printed everything that we needed to.
-            io::stdio::set_stderr(box io::util::NullWriter);
-            fail!();
-        }
-    }
-}
 
 pub fn main() {
-    std::os::set_exit_status(main_args(std::os::args().as_slice()));
+    std::os::set_exit_status(driver::main_args(std::os::args().as_slice()));
 }
 
-pub fn main_args(args: &[~str]) -> int {
-    let owned_args = args.to_owned();
-    monitor(proc() run_compiler(owned_args));
-    0
-}
index a5675f52671feb011c036fcf6298118c5888478f..d0b14f9e1302a1a782aa7f51af8fe357ad58b57b 100644 (file)
@@ -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 @@ fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
         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 @@ fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
             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 @@ fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
                 // 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() {
index 5faae72791d7e784bd20c5027d90839d5258b987..10d26922f750fe01dc224d1571c1affcf2b5fc5e 100644 (file)
@@ -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 {
index 7b5ef2bf2be629b0fa0f77047b68617c79d1b9ce..ae88d64e2f0c90bfce7dacb6707fcab5a880c290 100644 (file)
@@ -65,6 +65,7 @@
 use syntax::ast;
 
 use driver::session;
+use driver::config;
 use metadata::cstore;
 use metadata::csearch;
 use middle::ty;
@@ -80,7 +81,7 @@
 /// A mapping of all required dependencies for a particular flavor of output.
 ///
 /// This is local to the tcx, and is generally relevant to one session.
-pub type Dependencies = HashMap<session::CrateType, DependencyList>;
+pub type Dependencies = HashMap<config::CrateType, DependencyList>;
 
 pub fn calculate(tcx: &ty::ctxt) {
     let mut fmts = tcx.dependency_formats.borrow_mut();
@@ -91,11 +92,11 @@ pub fn calculate(tcx: &ty::ctxt) {
 }
 
 fn calculate_type(sess: &session::Session,
-                  ty: session::CrateType) -> DependencyList {
+                  ty: config::CrateType) -> DependencyList {
     match ty {
         // If the global prefer_dynamic switch is turned off, first attempt
         // static linkage (this can fail).
-        session::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => {
+        config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => {
             match attempt_static(sess) {
                 Some(v) => return v,
                 None => {}
@@ -104,11 +105,11 @@ fn calculate_type(sess: &session::Session,
 
         // No linkage happens with rlibs, we just needed the metadata (which we
         // got long ago), so don't bother with anything.
-        session::CrateTypeRlib => return Vec::new(),
+        config::CrateTypeRlib => return Vec::new(),
 
         // Staticlibs must have all static dependencies. If any fail to be
         // found, we generate some nice pretty errors.
-        session::CrateTypeStaticlib => {
+        config::CrateTypeStaticlib => {
             match attempt_static(sess) {
                 Some(v) => return v,
                 None => {}
@@ -123,7 +124,7 @@ fn calculate_type(sess: &session::Session,
         }
 
         // Everything else falls through below
-        session::CrateTypeExecutable | session::CrateTypeDylib => {},
+        config::CrateTypeExecutable | config::CrateTypeDylib => {},
     }
 
     let mut formats = HashMap::new();
index a17c8fb5c433e1c08c980a8919fc0f8b259077b5..1b7ed90237fd97b57ea3bd47fae57d8c2a591e05 100644 (file)
@@ -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 @@ fn visit_item(&mut self, item: &Item, _:()) {
 
 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");
index 7dad6473478c13250ac705f660c9055fe46fb047..49e607f12406c2da081bb0220a0a87b9152d760d 100644 (file)
@@ -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,
index b456ec224fe7e8e94fbdab35764d79e6f285d002..abb9be62dd8d419aa3860d780c4f3600441a865e 100644 (file)
 #![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};
index 6c4566c09aa7aabfc40a4bf92b6df01d8d90f992..4562f27536fc8f47ff8e739cf8660ef12c7643e3 100644 (file)
@@ -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<u8> {
     use flate;
 
     let any_library = cx.sess().crate_types.borrow().iter().any(|ty| {
-        *ty != session::CrateTypeExecutable
+        *ty != config::CrateTypeExecutable
     });
     if !any_library {
         return Vec::new()
index bfbd638be520cef57d8c1ae45691918651cd5397..1f4ea02bcc6481e172952c311b16547ee8ef1891 100644 (file)
@@ -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;
index f46c323232657683f241b33780066960eca9444b..777c03fa6068b7a4e31da2c8c4acb07b0c399b37 100644 (file)
@@ -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};
index a165549dacabb34dd64e8cdd6637a8169287d8cb..ec43e6e286f7dcadb8dd4af07ec89b15a459cc2c 100644 (file)
@@ -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::*;
index 304aa9b4025b532a1ca55764eccb00fc815b1d51..1e56604983f5f6d49fd824bb7cb66730e7111f6a 100644 (file)
@@ -125,8 +125,8 @@ struct List {
 */
 
 
-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)
                 }
index 49297e919ec60b9ddfdacbc9fb1924fe3c392f4d..83300f6dba705ec244f23ae2cb2a3615acd3006d 100644 (file)
@@ -61,7 +61,7 @@
 
 #![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 => {}
index d65d5a1e458e6c1f2b97a0e9f66db72b5ecfbc7d..e2684b3be693ed94bf606ff1f53f6aab50a484e8 100644 (file)
@@ -60,19 +60,20 @@ pub struct CrateAnalysis {
 fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<~str>)
                        -> (DocContext, CrateAnalysis) {
     use syntax::codemap::dummy_spanned;
-    use rustc::driver::driver::{FileInput, build_configuration,
+    use rustc::driver::driver::{FileInput,
                                 phase_1_parse_input,
                                 phase_2_configure_and_expand,
                                 phase_3_run_analysis_passes};
+    use rustc::driver::config::build_configuration;
 
     let input = FileInput(cpath.clone());
 
-    let sessopts = driver::session::Options {
+    let sessopts = driver::config::Options {
         maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
         addl_lib_search_paths: RefCell::new(libs),
-        crate_types: vec!(driver::session::CrateTypeDylib),
+        crate_types: vec!(driver::config::CrateTypeDylib),
         lint_opts: vec!((lint::Warnings, lint::allow)),
-        ..rustc::driver::session::basic_options().clone()
+        ..rustc::driver::config::basic_options().clone()
     };
 
 
@@ -81,9 +82,9 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<~str>)
     let span_diagnostic_handler =
         syntax::diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
-    let sess = driver::driver::build_session_(sessopts,
-                                              Some(cpath.clone()),
-                                              span_diagnostic_handler);
+    let sess = driver::session::build_session_(sessopts,
+                                               Some(cpath.clone()),
+                                               span_diagnostic_handler);
 
     let mut cfg = build_configuration(&sess);
     for cfg_ in cfgs.move_iter() {
index 72b474147335c7002c5fc1f67ca46ea2f01537be..3e87a2539c28acc04cc3044ba399ffc78c9b5d80 100644 (file)
@@ -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;
     }
 
index c8a19183485e1e61330ec9ff8a923058f50711b3..8a631fdcdd08cf2b16b2055f84522b140abc6e95 100644 (file)
@@ -19,6 +19,7 @@
 use collections::{HashSet, HashMap};
 use testing;
 use rustc::back::link;
+use rustc::driver::config;
 use rustc::driver::driver;
 use rustc::driver::session;
 use rustc::metadata::creader::Loader;
@@ -43,11 +44,11 @@ pub fn run(input: &str,
     let input_path = Path::new(input);
     let input = driver::FileInput(input_path.clone());
 
-    let sessopts = session::Options {
+    let sessopts = config::Options {
         maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
         addl_lib_search_paths: RefCell::new(libs.clone()),
-        crate_types: vec!(session::CrateTypeDylib),
-        ..session::basic_options().clone()
+        crate_types: vec!(config::CrateTypeDylib),
+        ..config::basic_options().clone()
     };
 
 
@@ -56,11 +57,11 @@ pub fn run(input: &str,
     let span_diagnostic_handler =
     diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
-    let sess = driver::build_session_(sessopts,
+    let sess = session::build_session_(sessopts,
                                       Some(input_path.clone()),
                                       span_diagnostic_handler);
 
-    let mut cfg = driver::build_configuration(&sess);
+    let mut cfg = config::build_configuration(&sess);
     cfg.extend(cfgs.move_iter().map(|cfg_| {
         let cfg_ = token::intern_and_get_ident(cfg_);
         @dummy_spanned(ast::MetaWord(cfg_))
@@ -101,17 +102,17 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
     let test = maketest(test, cratename, loose_feature_gating);
     let input = driver::StrInput(test);
 
-    let sessopts = session::Options {
+    let sessopts = config::Options {
         maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
         addl_lib_search_paths: RefCell::new(libs),
-        crate_types: vec!(session::CrateTypeExecutable),
+        crate_types: vec!(config::CrateTypeExecutable),
         output_types: vec!(link::OutputTypeExe),
         no_trans: no_run,
-        cg: session::CodegenOptions {
+        cg: config::CodegenOptions {
             prefer_dynamic: true,
-            .. session::basic_codegen_options()
+            .. config::basic_codegen_options()
         },
-        ..session::basic_options().clone()
+        ..config::basic_options().clone()
     };
 
     // Shuffle around a few input and output handles here. We're going to pass
@@ -142,13 +143,13 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
     let span_diagnostic_handler =
         diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
-    let sess = driver::build_session_(sessopts,
+    let sess = session::build_session_(sessopts,
                                       None,
                                       span_diagnostic_handler);
 
     let outdir = TempDir::new("rustdoctest").expect("rustdoc needs a tempdir");
     let out = Some(outdir.path().clone());
-    let cfg = driver::build_configuration(&sess);
+    let cfg = config::build_configuration(&sess);
     driver::compile_input(sess, cfg, &input, &out, &None);
 
     if no_run { return }