(index<- )        ./librustc/rustc.rs

   1  // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
   2  // file at the top-level directory of this distribution and at
   3  // http://rust-lang.org/COPYRIGHT.
   4  //
   5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
   6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
   7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
   8  // option. This file may not be copied, modified, or distributed
   9  // except according to those terms.
  10  
  11  #[link(name = "rustc",
  12         vers = "0.9-pre",
  13         uuid = "0ce89b41-2f92-459e-bbc1-8f5fe32f16cf",
  14         url = "https://github.com/mozilla/rust/tree/master/src/rustc")];
  15  
  16  #[comment = "The Rust compiler"];
  17  #[license = "MIT/ASL2"];
  18  #[crate_type = "lib"];
  19  
  20  #[feature(macro_rules, globs, struct_variant)];
  21  
  22  // Rustc tasks always run on a fixed_stack_segment, so code in this
  23  // module can call C functions (in particular, LLVM functions) with
  24  // impunity.
  25  #[allow(cstack)];
  26  
  27  extern mod extra;
  28  extern mod syntax;
  29  
  30  use driver::driver::{host_triple, optgroups, early_error};
  31  use driver::driver::{str_input, file_input, build_session_options};
  32  use driver::driver::{build_session, build_configuration, parse_pretty};
  33  use driver::driver::{PpMode, pretty_print_input, list_metadata};
  34  use driver::driver::{compile_input};
  35  use driver::session;
  36  use middle::lint;
  37  
  38  use std::comm;
  39  use std::io;
  40  use std::num;
  41  use std::os;
  42  use std::result;
  43  use std::str;
  44  use std::task;
  45  use std::vec;
  46  use extra::getopts::groups;
  47  use extra::getopts;
  48  use syntax::codemap;
  49  use syntax::diagnostic::Emitter;
  50  use syntax::diagnostic;
  51  
  52  pub mod middle {
  53      pub mod trans;
  54      pub mod ty;
  55      pub mod subst;
  56      pub mod resolve;
  57      pub mod typeck;
  58      pub mod check_loop;
  59      pub mod check_match;
  60      pub mod check_const;
  61      pub mod lint;
  62      pub mod borrowck;
  63      pub mod dataflow;
  64      pub mod mem_categorization;
  65      pub mod liveness;
  66      pub mod kind;
  67      pub mod freevars;
  68      pub mod pat_util;
  69      pub mod region;
  70      pub mod const_eval;
  71      pub mod astencode;
  72      pub mod lang_items;
  73      pub mod privacy;
  74      pub mod moves;
  75      pub mod entry;
  76      pub mod effect;
  77      pub mod reachable;
  78      pub mod graph;
  79      pub mod cfg;
  80      pub mod stack_check;
  81  }
  82  
  83  pub mod front {
  84      pub mod config;
  85      pub mod test;
  86      pub mod std_inject;
  87      pub mod assign_node_ids;
  88      pub mod feature_gate;
  89  }
  90  
  91  pub mod back {
  92      pub mod link;
  93      pub mod abi;
  94      pub mod upcall;
  95      pub mod arm;
  96      pub mod mips;
  97      pub mod x86;
  98      pub mod x86_64;
  99      pub mod rpath;
 100      pub mod target_strs;
 101  }
 102  
 103  pub mod metadata;
 104  
 105  pub mod driver;
 106  
 107  pub mod util {
 108      pub mod common;
 109      pub mod ppaux;
 110  }
 111  
 112  pub mod lib {
 113      pub mod llvm;
 114  }
 115  
 116  // A curious inner module that allows ::std::foo to be available in here for
 117  // macros.
 118  /*
 119  mod std {
 120      pub use std::clone;
 121      pub use std::cmp;
 122      pub use std::os;
 123      pub use std::str;
 124      pub use std::sys;
 125      pub use std::to_bytes;
 126      pub use std::unstable;
 127      pub use extra::serialize;
 128  }
 129  */
 130  
 131  pub fn version(argv0&str) {
 132      let vers = match option_env!("CFG_VERSION") {
 133          Some(vers) => vers,
 134          None => "unknown version"
 135      };
 136      println!("{} {}", argv0, vers);
 137      println!("host: {}", host_triple());
 138  }
 139  
 140  pub fn usage(argv0&str) {
 141      let message = format!("Usage: {} [OPTIONS] INPUT", argv0);
 142      println!("{}\n\
 143  Additional help:
 144      -W help             Print 'lint' options and default settings
 145      -Z help             Print internal options for debugging rustc\n",
 146                groups::usage(message, optgroups()));
 147  }
 148  
 149  pub fn describe_warnings() {
 150      use extra::sort::Sort;
 151      println("
 152  Available lint options:
 153      -W <foo>           Warn about <foo>
 154      -A <foo>           Allow <foo>
 155      -D <foo>           Deny <foo>
 156      -F <foo>           Forbid <foo> (deny, and deny all overrides)
 157  ");
 158  
 159      let lint_dict = lint::get_lint_dict();
 160      let mut lint_dict = lint_dict.move_iter()
 161                                   .map(|(k, v)| (v, k))
 162                                   .collect::<~[(lint::LintSpec, &'static str)]>();
 163      lint_dict.qsort();
 164  
 165      let mut max_key = 0;
 166      for &(_, name) in lint_dict.iter() {
 167          max_key = num::max(name.len(), max_key);
 168      }
 169      fn padded(maxuint, s&str) -> ~str {
 170          str::from_utf8(vec::from_elem(max - s.len(), ' ' as u8)) + s
 171      }
 172      println("\nAvailable lint checks:\n");
 173      println!("    {}  {:7.7s}  {}",
 174               padded(max_key, "name"), "default", "meaning");
 175      println!("    {}  {:7.7s}  {}\n",
 176               padded(max_key, "----"), "-------", "-------");
 177      for (spec, name) in lint_dict.move_iter() {
 178          let name = name.replace("_", "-");
 179          println!("    {}  {:7.7s}  {}",
 180                   padded(max_key, name),
 181                   lint::level_to_str(spec.default),
 182                   spec.desc);
 183      }
 184      io::println("");
 185  }
 186  
 187  pub fn describe_debug_flags() {
 188      println("\nAvailable debug options:\n");
 189      let r = session::debugging_opts_map();
 190      for tuple in r.iter() {
 191          match *tuple {
 192              (ref name, ref desc, _) => {
 193                  println!("    -Z {:>20s} -- {}", *name, *desc);
 194              }
 195          }
 196      }
 197  }
 198  
 199  pub fn run_compiler(args&[~str], demitter@diagnostic::Emitter) {
 200      let mut args = args.to_owned();
 201      let binary = args.shift().to_managed();
 202  
 203      if args.is_empty() { usage(binary); return; }
 204  
 205      let matches =
 206          &match getopts::groups::getopts(args, optgroups()) {
 207            Ok(m) => m,
 208            Err(f) => {
 209              early_error(demitter, f.to_err_msg());
 210            }
 211          };
 212  
 213      if matches.opt_present("h") || matches.opt_present("help") {
 214          usage(binary);
 215          return;
 216      }
 217  
 218      // Display the available lint options if "-W help" or only "-W" is given.
 219      let lint_flags = vec::append(matches.opt_strs("W"),
 220                                   matches.opt_strs("warn"));
 221  
 222      let show_lint_options = lint_flags.iter().any(|x| x == &~"help") ||
 223          (matches.opt_present("W") && lint_flags.is_empty());
 224  
 225      if show_lint_options {
 226          describe_warnings();
 227          return;
 228      }
 229  
 230      let r = matches.opt_strs("Z");
 231      if r.iter().any(|x| x == &~"help") {
 232          describe_debug_flags();
 233          return;
 234      }
 235  
 236      if matches.opt_str("passes") == Some(~"list") {
 237          unsafe { lib::llvm::llvm::LLVMRustPrintPasses(); }
 238          return;
 239      }
 240  
 241      if matches.opt_present("v") || matches.opt_present("version") {
 242          version(binary);
 243          return;
 244      }
 245      let input = match matches.free.len() {
 246        0u => early_error(demitter, "no input filename given"),
 247        1u => {
 248          let ifile = matches.free[0].as_slice();
 249          if "-" == ifile {
 250              let src = str::from_utf8(io::stdin().read_whole_stream());
 251              str_input(src.to_managed())
 252          } else {
 253              file_input(Path::new(ifile))
 254          }
 255        }
 256        _ => early_error(demitter, "multiple input filenames provided")
 257      };
 258  
 259      let sopts = build_session_options(binary, matches, demitter);
 260      let sess = build_session(sopts, demitter);
 261      let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
 262      let ofile = matches.opt_str("o").map(|o| Path::new(o));
 263      let cfg = build_configuration(sess);
 264      let pretty = do matches.opt_default("pretty", "normal").map |a| {
 265          parse_pretty(sess, a)
 266      };
 267      match pretty {
 268        Some::<PpMode>(ppm) => {
 269          pretty_print_input(sess, cfg, &input, ppm);
 270          return;
 271        }
 272        None::<PpMode> => {/* continue */ }
 273      }
 274      let ls = matches.opt_present("ls");
 275      if ls {
 276          match input {
 277            file_input(ref ifile) => {
 278              list_metadata(sess, &(*ifile), io::stdout());
 279            }
 280            str_input(_) => {
 281              early_error(demitter, "can not list metadata for stdin");
 282            }
 283          }
 284          return;
 285      }
 286  
 287      compile_input(sess, cfg, &input, &odir, &ofile);
 288  }
 289  
 290  #[deriving(Eq)]
 291  pub enum monitor_msg {
 292      fatal,
 293      done,
 294  }
 295  
 296  struct RustcEmitter {
 297      ch_capture: comm::SharedChan<monitor_msg>
 298  }
 299  
 300  impl diagnostic::Emitter for RustcEmitter {
 301      fn emit(&self,
 302              cmspOption<(@codemap::CodeMap, codemap::Span)>,
 303              msg&str,
 304              lvldiagnostic::level) {
 305          if lvl == diagnostic::fatal {
 306              self.ch_capture.send(fatal)
 307          }
 308  
 309          diagnostic::DefaultEmitter.emit(cmsp, msg, lvl)
 310      }
 311  }
 312  
 313  /*
 314  This is a sanity check that any failure of the compiler is performed
 315  through the diagnostic module and reported properly - we shouldn't be calling
 316  plain-old-fail on any execution path that might be taken. Since we have
 317  console logging off by default, hitting a plain fail statement would make the
 318  compiler silently exit, which would be terrible.
 319  
 320  This method wraps the compiler in a subtask and injects a function into the
 321  diagnostic emitter which records when we hit a fatal error. If the task
 322  fails without recording a fatal error then we've encountered a compiler
 323  bug and need to present an error.
 324  */
 325  pub fn monitor(f~fn(@diagnostic::Emitter)) {
 326      use std::comm::*;
 327  
 328      // XXX: This is a hack for newsched since it doesn't support split stacks.
 329      // rustc needs a lot of stack!
 330      static STACK_SIZE: uint = 6000000;
 331  
 332      let (p, ch) = stream();
 333      let ch = SharedChan::new(ch);
 334      let ch_capture = ch.clone();
 335      let mut task_builder = task::task();
 336      task_builder.supervised();
 337  
 338      // XXX: Hacks on hacks. If the env is trying to override the stack size
 339      // then *don't* set it explicitly.
 340      if os::getenv("RUST_MIN_STACK").is_none() {
 341          task_builder.opts.stack_size = Some(STACK_SIZE);
 342      }
 343  
 344      match do task_builder.try {
 345          let ch = ch_capture.clone();
 346          // The 'diagnostics emitter'. Every error, warning, etc. should
 347          // go through this function.
 348          let demitter = @RustcEmitter {
 349              ch_capture: ch.clone(),
 350          } as @diagnostic::Emitter;
 351  
 352          struct finally {
 353              ch: SharedChan<monitor_msg>,
 354          }
 355  
 356          impl Drop for finally {
 357              fn drop(&mut self) { self.ch.send(done); }
 358          }
 359  
 360          let _finally = finally { ch: ch };
 361  
 362          f(demitter);
 363  
 364          // Due reasons explain in #7732, if there was a jit execution context it
 365          // must be consumed and passed along to our parent task.
 366          back::link::jit::consume_engine()
 367      } {
 368          result::Ok(_) => { /* fallthrough */ }
 369          result::Err(_) => {
 370              // Task failed without emitting a fatal diagnostic
 371              if p.recv() == done {
 372                  diagnostic::DefaultEmitter.emit(
 373                      None,
 374                      diagnostic::ice_msg("unexpected failure"),
 375                      diagnostic::error);
 376  
 377                  let xs = [
 378                      ~"the compiler hit an unexpected failure path. \
 379                       this is a bug",
 380                      ~"try running with RUST_LOG=rustc=1 \
 381                       to get further details and report the results \
 382                       to github.com/mozilla/rust/issues"
 383                  ];
 384                  for note in xs.iter() {
 385                      diagnostic::DefaultEmitter.emit(None,
 386                                                      *note,
 387                                                      diagnostic::note)
 388                  }
 389              }
 390              // Fail so the process returns a failure code
 391              fail2!();
 392          }
 393      }
 394  }
 395  
 396  pub fn main() {
 397      std::os::set_exit_status(main_args(std::os::args()));
 398  }
 399  
 400  pub fn main_args(args&[~str]) -> int {
 401      let owned_args = args.to_owned();
 402      do monitor |demitter| {
 403          run_compiler(owned_args, demitter);
 404      }
 405  
 406      return 0;
 407  }

librustc/rustc.rs:324:3-324:3 -fn- definition:
*/
pub fn monitor(f: ~fn(@diagnostic::Emitter)) {
references:-
402:     do monitor |demitter| {


librustc/rustc.rs:352:8-352:8 -struct- definition:
        struct finally {
            ch: SharedChan<monitor_msg>,
references:-
356:         impl Drop for finally {
360:         let _finally = finally { ch: ch };


librustc/rustc.rs:139:1-139:1 -fn- definition:

pub fn usage(argv0: &str) {
references:-
203:     if args.is_empty() { usage(binary); return; }
214:         usage(binary);


librustc/rustc.rs:290:16-290:16 -enum- definition:
#[deriving(Eq)]
pub enum monitor_msg {
references:-
290: #[deriving(Eq)]
297:     ch_capture: comm::SharedChan<monitor_msg>
290: #[deriving(Eq)]
353:             ch: SharedChan<monitor_msg>,
290: #[deriving(Eq)]


librustc/rustc.rs:169:4-169:4 -fn- definition:
    fn padded(max: uint, s: &str) -> ~str {
        str::from_utf8(vec::from_elem(max - s.len(), ' ' as u8)) + s
references:-
174:              padded(max_key, "name"), "default", "meaning");
180:                  padded(max_key, name),
176:              padded(max_key, "----"), "-------", "-------");


librustc/rustc.rs:198:1-198:1 -fn- definition:

pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) {
references:-
403:         run_compiler(owned_args, demitter);


librustc/rustc.rs:295:1-295:1 -struct- definition:

struct RustcEmitter {
references:-
300: impl diagnostic::Emitter for RustcEmitter {
348:         let demitter = @RustcEmitter {


librustc/rustc.rs:399:1-399:1 -fn- definition:

pub fn main_args(args: &[~str]) -> int {
references:-
397:     std::os::set_exit_status(main_args(std::os::args()));


librustc/rustc.rs:148:1-148:1 -fn- definition:

pub fn describe_warnings() {
references:-
226:         describe_warnings();


librustc/rustc.rs:130:1-130:1 -fn- definition:

pub fn version(argv0: &str) {
references:-
242:         version(binary);


librustc/rustc.rs:186:1-186:1 -fn- definition:

pub fn describe_debug_flags() {
references:-
232:         describe_debug_flags();