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

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
    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  
   12  use back::link;
   13  use back::{arm, x86, x86_64, mips};
   14  use driver::session::{Aggressive, CrateTypeExecutable, CrateType,
   15                        FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
   16  use driver::session::{Session, No, Less, Default};
   17  use driver::session;
   18  use front;
   19  use lib::llvm::llvm;
   20  use lib::llvm::{ContextRef, ModuleRef};
   21  use metadata::common::LinkMeta;
   22  use metadata::{creader, filesearch};
   23  use metadata::cstore::CStore;
   24  use metadata::creader::Loader;
   25  use metadata;
   26  use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
   27  use middle::dependency_format;
   28  use middle;
   29  use util::common::time;
   30  use util::ppaux;
   31  use util::nodemap::{NodeMap, NodeSet};
   32  
   33  use serialize::{json, Encodable};
   34  
   35  use std::cell::{Cell, RefCell};
   36  use std::io;
   37  use std::io::fs;
   38  use std::io::MemReader;
   39  use std::os;
   40  use getopts::{optopt, optmulti, optflag, optflagopt};
   41  use getopts;
   42  use syntax::ast;
   43  use syntax::abi;
   44  use syntax::attr;
   45  use syntax::attr::{AttrMetaMethods};
   46  use syntax::codemap;
   47  use syntax::crateid::CrateId;
   48  use syntax::diagnostic;
   49  use syntax::diagnostic::Emitter;
   50  use syntax::ext::base::CrateLoader;
   51  use syntax::parse;
   52  use syntax::parse::token::InternedString;
   53  use syntax::parse::token;
   54  use syntax::print::{pp, pprust};
   55  use syntax;
   56  
   57  pub enum PpMode {
   58      PpmNormal,
   59      PpmExpanded,
   60      PpmTyped,
   61      PpmIdentified,
   62      PpmExpandedIdentified
   63  }
   64  
   65  /**
   66   * The name used for source code that doesn't originate in a file
   67   * (e.g. source from stdin or a string)
   68   */
   69  pub fn anon_src() -> ~str {
   70      "<anon>".to_str()
   71  }
   72  
   73  pub fn source_name(input: &Input) -> ~str {
   74      match *input {
   75          // FIXME (#9639): This needs to handle non-utf8 paths
   76          FileInput(ref ifile) => ifile.as_str().unwrap().to_str(),
   77          StrInput(_) => anon_src()
   78      }
   79  }
   80  
   81  pub fn default_configuration(sess: &Session) ->
   82     ast::CrateConfig {
   83      let tos = match sess.targ_cfg.os {
   84          abi::OsWin32 =>   InternedString::new("win32"),
   85          abi::OsMacos =>   InternedString::new("macos"),
   86          abi::OsLinux =>   InternedString::new("linux"),
   87          abi::OsAndroid => InternedString::new("android"),
   88          abi::OsFreebsd => InternedString::new("freebsd"),
   89      };
   90  
   91      // ARM is bi-endian, however using NDK seems to default
   92      // to little-endian unless a flag is provided.
   93      let (end,arch,wordsz) = match sess.targ_cfg.arch {
   94          abi::X86 =>    ("little", "x86",    "32"),
   95          abi::X86_64 => ("little", "x86_64", "64"),
   96          abi::Arm =>    ("little", "arm",    "32"),
   97          abi::Mips =>   ("big",    "mips",   "32")
   98      };
   99  
  100      let fam = match sess.targ_cfg.os {
  101          abi::OsWin32 => InternedString::new("windows"),
  102          _ => InternedString::new("unix")
  103      };
  104  
  105      let mk = attr::mk_name_value_item_str;
  106      return vec!(// Target bindings.
  107           attr::mk_word_item(fam.clone()),
  108           mk(InternedString::new("target_os"), tos),
  109           mk(InternedString::new("target_family"), fam),
  110           mk(InternedString::new("target_arch"), InternedString::new(arch)),
  111           mk(InternedString::new("target_endian"), InternedString::new(end)),
  112           mk(InternedString::new("target_word_size"),
  113              InternedString::new(wordsz))
  114      );
  115  }
  116  
  117  pub fn append_configuration(cfg: &mut ast::CrateConfig,
  118                              nameInternedString) {
  119      if !cfg.iter().any(|mi| mi.name() == name) {
  120          cfg.push(attr::mk_word_item(name))
  121      }
  122  }
  123  
  124  pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
  125      // Combine the configuration requested by the session (command line) with
  126      // some default and generated configuration items
  127      let default_cfg = default_configuration(sess);
  128      let mut user_cfg = sess.opts.cfg.clone();
  129      // If the user wants a test runner, then add the test cfg
  130      if sess.opts.test {
  131          append_configuration(&mut user_cfg, InternedString::new("test"))
  132      }
  133      // If the user requested GC, then add the GC cfg
  134      append_configuration(&mut user_cfg, if sess.opts.gc {
  135          InternedString::new("gc")
  136      } else {
  137          InternedString::new("nogc")
  138      });
  139      user_cfg.move_iter().collect::<Vec<_>>().append(default_cfg.as_slice())
  140  }
  141  
  142  // Convert strings provided as --cfg [cfgspec] into a crate_cfg
  143  fn parse_cfgspecs(cfgspecsVec<~str> )
  144                    -> ast::CrateConfig {
  145      cfgspecs.move_iter().map(|s| {
  146          parse::parse_meta_from_source_str("cfgspec".to_strbuf(),
  147                                            s.to_strbuf(),
  148                                            Vec::new(),
  149                                            &parse::new_parse_sess())
  150      }).collect::<ast::CrateConfig>()
  151  }
  152  
  153  pub enum Input {
  154      /// Load source from file
  155      FileInput(Path),
  156      /// The string is the source
  157      StrInput(~str)
  158  }
  159  
  160  impl Input {
  161      fn filestem(&self) -> ~str {
  162          match *self {
  163              FileInput(ref ifile) => ifile.filestem_str().unwrap().to_str(),
  164              StrInput(_) => "rust_out".to_owned(),
  165          }
  166      }
  167  }
  168  
  169  
  170  pub fn phase_1_parse_input(sess: &Session, cfgast::CrateConfig, input: &Input)
  171      -> ast::Crate {
  172      let krate = time(sess.time_passes(), "parsing", (), |_| {
  173          match *input {
  174              FileInput(ref file) => {
  175                  parse::parse_crate_from_file(&(*file), cfg.clone(), &sess.parse_sess)
  176              }
  177              StrInput(ref src) => {
  178                  parse::parse_crate_from_source_str(anon_src().to_strbuf(),
  179                                                     src.to_strbuf(),
  180                                                     cfg.clone(),
  181                                                     &sess.parse_sess)
  182              }
  183          }
  184      });
  185  
  186      if sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0 {
  187          let mut stdout = io::BufferedWriter::new(io::stdout());
  188          let mut json = json::PrettyEncoder::new(&mut stdout);
  189          // unwrapping so IoError isn't ignored
  190          krate.encode(&mut json).unwrap();
  191      }
  192  
  193      if sess.show_span() {
  194          front::show_span::run(sess, &krate);
  195      }
  196  
  197      krate
  198  }
  199  
  200  // For continuing compilation after a parsed crate has been
  201  // modified
  202  
  203  /// Run the "early phases" of the compiler: initial `cfg` processing,
  204  /// syntax expansion, secondary `cfg` expansion, synthesis of a test
  205  /// harness if one is to be provided and injection of a dependency on the
  206  /// standard library and prelude.
  207  pub fn phase_2_configure_and_expand(sess: &Session,
  208                                      loader: &mut CrateLoader,
  209                                      mut krateast::Crate,
  210                                      crate_id: &CrateId)
  211                                      -> (ast::Crate, syntax::ast_map::Map) {
  212      let time_passes = sess.time_passes();
  213  
  214      *sess.crate_types.borrow_mut() = session::collect_crate_types(sess, krate.attrs.as_slice());
  215  
  216      time(time_passes, "gated feature checking", (), |_|
  217           front::feature_gate::check_crate(sess, &krate));
  218  
  219      krate = time(time_passes, "crate injection", krate, |krate|
  220                   front::std_inject::maybe_inject_crates_ref(sess, krate));
  221  
  222      // strip before expansion to allow macros to depend on
  223      // configuration variables e.g/ in
  224      //
  225      //   #[macro_escape] #[cfg(foo)]
  226      //   mod bar { macro_rules! baz!(() => {{}}) }
  227      //
  228      // baz! should not use this definition unless foo is enabled.
  229  
  230      krate = time(time_passes, "configuration 1", krate, |krate|
  231                   front::config::strip_unconfigured_items(krate));
  232  
  233      krate = time(time_passes, "expansion", krate, |krate| {
  234          // Windows dlls do not have rpaths, so they don't know how to find their
  235          // dependencies. It's up to use to tell the system where to find all the
  236          // dependent dlls. Note that this uses cfg!(windows) as opposed to
  237          // targ_cfg because syntax extensions are always loaded for the host
  238          // compiler, not for the target.
  239          if cfg!(windows) {
  240              sess.host_filesearch().add_dylib_search_paths();
  241          }
  242          let cfg = syntax::ext::expand::ExpansionConfig {
  243              loader: loader,
  244              deriving_hash_type_parameter: sess.features.default_type_params.get(),
  245              crate_id: crate_id.clone(),
  246          };
  247          syntax::ext::expand::expand_crate(&sess.parse_sess,
  248                                            cfg,
  249                                            krate)
  250      });
  251  
  252      // strip again, in case expansion added anything with a #[cfg].
  253      krate = time(time_passes, "configuration 2", krate, |krate|
  254                   front::config::strip_unconfigured_items(krate));
  255  
  256      krate = time(time_passes, "maybe building test harness", krate, |krate|
  257                   front::test::modify_for_testing(sess, krate));
  258  
  259      krate = time(time_passes, "prelude injection", krate, |krate|
  260                   front::std_inject::maybe_inject_prelude(sess, krate));
  261  
  262      let (krate, map) = time(time_passes, "assinging node ids and indexing ast", krate, |krate|
  263           front::assign_node_ids_and_map::assign_node_ids_and_map(sess, krate));
  264  
  265      if sess.opts.debugging_opts & session::AST_JSON != 0 {
  266          let mut stdout = io::BufferedWriter::new(io::stdout());
  267          let mut json = json::PrettyEncoder::new(&mut stdout);
  268          // unwrapping so IoError isn't ignored
  269          krate.encode(&mut json).unwrap();
  270      }
  271  
  272      (krate, map)
  273  }
  274  
  275  pub struct CrateAnalysis {
  276      pub exp_map2: middle::resolve::ExportMap2,
  277      pub exported_items: middle::privacy::ExportedItems,
  278      pub public_items: middle::privacy::PublicItems,
  279      pub ty_cx: ty::ctxt,
  280      pub reachable: NodeSet,
  281  }
  282  
  283  /// Run the resolution, typechecking, region checking and other
  284  /// miscellaneous analysis passes on the crate. Return various
  285  /// structures carrying the results of the analysis.
  286  pub fn phase_3_run_analysis_passes(sessSession,
  287                                     krate: &ast::Crate,
  288                                     ast_mapsyntax::ast_map::Map) -> CrateAnalysis {
  289  
  290      let time_passes = sess.time_passes();
  291  
  292      time(time_passes, "external crate/lib resolution", (), |_|
  293           creader::read_crates(&sess, krate));
  294  
  295      let lang_items = time(time_passes, "language item collection", (), |_|
  296                            middle::lang_items::collect_language_items(krate, &sess));
  297  
  298      let middle::resolve::CrateMap {
  299          def_map: def_map,
  300          exp_map2: exp_map2,
  301          trait_map: trait_map,
  302          external_exports: external_exports,
  303          last_private_map: last_private_map
  304      } =
  305          time(time_passes, "resolution", (), |_|
  306               middle::resolve::resolve_crate(&sess, &lang_items, krate));
  307  
  308      // Discard MTWT tables that aren't required past resolution.
  309      syntax::ext::mtwt::clear_tables();
  310  
  311      let named_region_map = time(time_passes, "lifetime resolution", (),
  312                                  |_| middle::resolve_lifetime::krate(&sess, krate));
  313  
  314      time(time_passes, "looking for entry point", (),
  315           |_| middle::entry::find_entry_point(&sess, krate, &ast_map));
  316  
  317      sess.macro_registrar_fn.set(
  318          time(time_passes, "looking for macro registrar", (), |_|
  319              syntax::ext::registrar::find_macro_registrar(
  320                  sess.diagnostic(), krate)));
  321  
  322      let freevars = time(time_passes, "freevar finding", (), |_|
  323                          freevars::annotate_freevars(&def_map, krate));
  324  
  325      let region_map = time(time_passes, "region resolution", (), |_|
  326                            middle::region::resolve_crate(&sess, krate));
  327  
  328      time(time_passes, "loop checking", (), |_|
  329           middle::check_loop::check_crate(&sess, krate));
  330  
  331      let ty_cx = ty::mk_ctxt(sess, def_map, named_region_map, ast_map,
  332                              freevars, region_map, lang_items);
  333  
  334      // passes are timed inside typeck
  335      typeck::check_crate(&ty_cx, trait_map, krate);
  336  
  337      time(time_passes, "check static items", (), |_|
  338           middle::check_static::check_crate(&ty_cx, krate));
  339  
  340      // These next two const passes can probably be merged
  341      time(time_passes, "const marking", (), |_|
  342           middle::const_eval::process_crate(krate, &ty_cx));
  343  
  344      time(time_passes, "const checking", (), |_|
  345           middle::check_const::check_crate(krate, &ty_cx));
  346  
  347      let maps = (external_exports, last_private_map);
  348      let (exported_items, public_items) =
  349              time(time_passes, "privacy checking", maps, |(a, b)|
  350                   middle::privacy::check_crate(&ty_cx, &exp_map2, a, b, krate));
  351  
  352      time(time_passes, "effect checking", (), |_|
  353           middle::effect::check_crate(&ty_cx, krate));
  354  
  355      time(time_passes, "match checking", (), |_|
  356           middle::check_match::check_crate(&ty_cx, krate));
  357  
  358      time(time_passes, "liveness checking", (), |_|
  359           middle::liveness::check_crate(&ty_cx, krate));
  360  
  361      time(time_passes, "borrow checking", (), |_|
  362           middle::borrowck::check_crate(&ty_cx, krate));
  363  
  364      time(time_passes, "kind checking", (), |_|
  365           kind::check_crate(&ty_cx, krate));
  366  
  367      let reachable_map =
  368          time(time_passes, "reachability checking", (), |_|
  369               reachable::find_reachable(&ty_cx, &exported_items));
  370  
  371      time(time_passes, "death checking", (), |_| {
  372          middle::dead::check_crate(&ty_cx,
  373                                    &exported_items,
  374                                    &reachable_map,
  375                                    krate)
  376      });
  377  
  378      time(time_passes, "lint checking", (), |_|
  379           lint::check_crate(&ty_cx, &exported_items, krate));
  380  
  381      CrateAnalysis {
  382          exp_map2: exp_map2,
  383          ty_cx: ty_cx,
  384          exported_items: exported_items,
  385          public_items: public_items,
  386          reachable: reachable_map,
  387      }
  388  }
  389  
  390  pub struct CrateTranslation {
  391      pub context: ContextRef,
  392      pub module: ModuleRef,
  393      pub metadata_module: ModuleRef,
  394      pub link: LinkMeta,
  395      pub metadata: Vec<u8>,
  396      pub reachable: Vec<~str>,
  397      pub crate_formats: dependency_format::Dependencies,
  398  }
  399  
  400  /// Run the translation phase to LLVM, after which the AST and analysis can
  401  /// be discarded.
  402  pub fn phase_4_translate_to_llvm(krateast::Crate,
  403                                   analysisCrateAnalysis,
  404                                   outputs: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
  405      let time_passes = analysis.ty_cx.sess.time_passes();
  406  
  407      time(time_passes, "resolving dependency formats", (), |_|
  408           dependency_format::calculate(&analysis.ty_cx));
  409  
  410      // Option dance to work around the lack of stack once closures.
  411      time(time_passes, "translation", (krate, analysis), |(krate, analysis)|
  412           trans::base::trans_crate(krate, analysis, outputs))
  413  }
  414  
  415  /// Run LLVM itself, producing a bitcode file, assembly file or object file
  416  /// as a side effect.
  417  pub fn phase_5_run_llvm_passes(sess: &Session,
  418                                 trans: &CrateTranslation,
  419                                 outputs: &OutputFilenames) {
  420      if sess.opts.cg.no_integrated_as {
  421          let output_type = link::OutputTypeAssembly;
  422  
  423          time(sess.time_passes(), "LLVM passes", (), |_|
  424              link::write::run_passes(sess, trans, [output_type], outputs));
  425  
  426          link::write::run_assembler(sess, outputs);
  427  
  428          // Remove assembly source, unless --save-temps was specified
  429          if !sess.opts.cg.save_temps {
  430              fs::unlink(&outputs.temp_path(link::OutputTypeAssembly)).unwrap();
  431          }
  432      } else {
  433          time(sess.time_passes(), "LLVM passes", (), |_|
  434              link::write::run_passes(sess,
  435                                      trans,
  436                                      sess.opts.output_types.as_slice(),
  437                                      outputs));
  438      }
  439  }
  440  
  441  /// Run the linker on any artifacts that resulted from the LLVM run.
  442  /// This should produce either a finished executable or library.
  443  pub fn phase_6_link_output(sess: &Session,
  444                             trans: &CrateTranslation,
  445                             outputs: &OutputFilenames) {
  446      time(sess.time_passes(), "linking", (), |_|
  447           link::link_binary(sess,
  448                             trans,
  449                             outputs,
  450                             &trans.link.crateid));
  451  }
  452  
  453  pub fn stop_after_phase_3(sess: &Session) -> bool {
  454     if sess.opts.no_trans {
  455          debug!("invoked with --no-trans, returning early from compile_input");
  456          return true;
  457      }
  458      return false;
  459  }
  460  
  461  pub fn stop_after_phase_1(sess: &Session) -> bool {
  462      if sess.opts.parse_only {
  463          debug!("invoked with --parse-only, returning early from compile_input");
  464          return true;
  465      }
  466      if sess.show_span() {
  467          return true;
  468      }
  469      return sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0;
  470  }
  471  
  472  pub fn stop_after_phase_2(sess: &Session) -> bool {
  473      if sess.opts.no_analysis {
  474          debug!("invoked with --no-analysis, returning early from compile_input");
  475          return true;
  476      }
  477      return sess.opts.debugging_opts & session::AST_JSON != 0;
  478  }
  479  
  480  pub fn stop_after_phase_5(sess: &Session) -> bool {
  481      if !sess.opts.output_types.iter().any(|&i| i == link::OutputTypeExe) {
  482          debug!("not building executable, returning early from compile_input");
  483          return true;
  484      }
  485      return false;
  486  }
  487  
  488  fn write_out_deps(sess: &Session,
  489                    input: &Input,
  490                    outputs: &OutputFilenames,
  491                    krate: &ast::Crate) {
  492      let id = link::find_crate_id(krate.attrs.as_slice(), outputs.out_filestem);
  493  
  494      let mut out_filenames = Vec::new();
  495      for output_type in sess.opts.output_types.iter() {
  496          let file = outputs.path(*output_type);
  497          match *output_type {
  498              link::OutputTypeExe => {
  499                  for output in sess.crate_types.borrow().iter() {
  500                      let p = link::filename_for_input(sess, *output, &id, &file);
  501                      out_filenames.push(p);
  502                  }
  503              }
  504              _ => { out_filenames.push(file); }
  505          }
  506      }
  507  
  508      // Write out dependency rules to the dep-info file if requested with
  509      // --dep-info
  510      let deps_filename = match sess.opts.write_dependency_info {
  511          // Use filename from --dep-file argument if given
  512          (true, Some(ref filename)) => filename.clone(),
  513          // Use default filename: crate source filename with extension replaced
  514          // by ".d"
  515          (true, None) => match *input {
  516              FileInput(..) => outputs.with_extension("d"),
  517              StrInput(..) => {
  518                  sess.warn("can not write --dep-info without a filename \
  519                             when compiling stdin.");
  520                  return
  521              },
  522          },
  523          _ => return,
  524      };
  525  
  526      let result = (|| {
  527          // Build a list of files used to compile the output and
  528          // write Makefile-compatible dependency rules
  529          let filesVec<~str> = sess.codemap().files.borrow()
  530                                     .iter().filter(|fmap| fmap.is_real_file())
  531                                     .map(|fmap| fmap.name.to_owned())
  532                                     .collect();
  533          let mut file = try!(io::File::create(&deps_filename));
  534          for path in out_filenames.iter() {
  535              try!(write!(&mut file as &mut Writer,
  536                            "{}{}\n\n", path.display(), files.connect(" ")));
  537          }
  538          Ok(())
  539      })();
  540  
  541      match result {
  542          Ok(()) => {}
  543          Err(e) => {
  544              sess.fatal(format!("error writing dependencies to `{}`: {}",
  545                                 deps_filename.display(), e));
  546          }
  547      }
  548  }
  549  
  550  pub fn compile_input(sessSession, cfgast::CrateConfig, input: &Input,
  551                       outdir: &Option<Path>, output: &Option<Path>) {
  552      // We need nested scopes here, because the intermediate results can keep
  553      // large chunks of memory alive and we want to free them as soon as
  554      // possible to keep the peak memory usage low
  555      let (outputs, trans, sess) = {
  556          let (outputs, expanded_crate, ast_map) = {
  557              let krate = phase_1_parse_input(&sess, cfg, input);
  558              if stop_after_phase_1(&sess) { return; }
  559              let outputs = build_output_filenames(input,
  560                                                   outdir,
  561                                                   output,
  562                                                   krate.attrs.as_slice(),
  563                                                   &sess);
  564              let loader = &mut Loader::new(&sess);
  565              let id = link::find_crate_id(krate.attrs.as_slice(),
  566                                           outputs.out_filestem);
  567              let (expanded_crate, ast_map) = phase_2_configure_and_expand(&sess, loader,
  568                                                                           krate, &id);
  569              (outputs, expanded_crate, ast_map)
  570          };
  571          write_out_deps(&sess, input, &outputs, &expanded_crate);
  572  
  573          if stop_after_phase_2(&sess) { return; }
  574  
  575          let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
  576          if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
  577          let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate,
  578                                                       analysis, &outputs);
  579  
  580          // Discard interned strings as they are no longer required.
  581          token::get_ident_interner().clear();
  582  
  583          (outputs, trans, tcx.sess)
  584      };
  585      phase_5_run_llvm_passes(&sess, &trans, &outputs);
  586      if stop_after_phase_5(&sess) { return; }
  587      phase_6_link_output(&sess, &trans, &outputs);
  588  }
  589  
  590  struct IdentifiedAnnotation;
  591  
  592  impl pprust::PpAnn for IdentifiedAnnotation {
  593      fn pre(&self,
  594             s&mut pprust::State,
  595             nodepprust::AnnNode) -> io::IoResult<()> {
  596          match node {
  597              pprust::NodeExpr(_) => s.popen(),
  598              _ => Ok(())
  599          }
  600      }
  601      fn post(&self,
  602              s&mut pprust::State,
  603              nodepprust::AnnNode) -> io::IoResult<()> {
  604          match node {
  605              pprust::NodeItem(item) => {
  606                  try!(pp::space(&mut s.s));
  607                  s.synth_comment(item.id.to_str().to_strbuf())
  608              }
  609              pprust::NodeBlock(blk) => {
  610                  try!(pp::space(&mut s.s));
  611                  s.synth_comment((format!("block {}", blk.id)).to_strbuf())
  612              }
  613              pprust::NodeExpr(expr) => {
  614                  try!(pp::space(&mut s.s));
  615                  try!(s.synth_comment(expr.id.to_str().to_strbuf()));
  616                  s.pclose()
  617              }
  618              pprust::NodePat(pat) => {
  619                  try!(pp::space(&mut s.s));
  620                  s.synth_comment((format!("pat {}", pat.id)).to_strbuf())
  621              }
  622          }
  623      }
  624  }
  625  
  626  struct TypedAnnotation {
  627      analysis: CrateAnalysis,
  628  }
  629  
  630  impl pprust::PpAnn for TypedAnnotation {
  631      fn pre(&self,
  632             s&mut pprust::State,
  633             nodepprust::AnnNode) -> io::IoResult<()> {
  634          match node {
  635              pprust::NodeExpr(_) => s.popen(),
  636              _ => Ok(())
  637          }
  638      }
  639      fn post(&self,
  640              s&mut pprust::State,
  641              nodepprust::AnnNode) -> io::IoResult<()> {
  642          let tcx = &self.analysis.ty_cx;
  643          match node {
  644              pprust::NodeExpr(expr) => {
  645                  try!(pp::space(&mut s.s));
  646                  try!(pp::word(&mut s.s, "as"));
  647                  try!(pp::space(&mut s.s));
  648                  try!(pp::word(&mut s.s,
  649                                  ppaux::ty_to_str(tcx, ty::expr_ty(tcx, expr))));
  650                  s.pclose()
  651              }
  652              _ => Ok(())
  653          }
  654      }
  655  }
  656  
  657  pub fn pretty_print_input(sessSession,
  658                            cfgast::CrateConfig,
  659                            input: &Input,
  660                            ppmPpMode,
  661                            ofileOption<Path>) {
  662      let krate = phase_1_parse_input(&sess, cfg, input);
  663      let id = link::find_crate_id(krate.attrs.as_slice(), input.filestem());
  664  
  665      let (krate, ast_map, is_expanded) = match ppm {
  666          PpmExpanded | PpmExpandedIdentified | PpmTyped => {
  667              let loader = &mut Loader::new(&sess);
  668              let (krate, ast_map) = phase_2_configure_and_expand(&sess, loader,
  669                                                                  krate, &id);
  670              (krate, Some(ast_map), true)
  671          }
  672          _ => (krate, None, false)
  673      };
  674  
  675      let src_name = source_name(input);
  676      let src = Vec::from_slice(sess.codemap().get_filemap(src_name).src.as_bytes());
  677      let mut rdr = MemReader::new(src);
  678  
  679      let out = match ofile {
  680          None => box io::stdout() as Box<Writer>,
  681          Some(p) => {
  682              let r = io::File::create(&p);
  683              match r {
  684                  Ok(w) => box w as Box<Writer>,
  685                  Err(e) => fail!("print-print failed to open {} due to {}",
  686                                  p.display(), e),
  687              }
  688          }
  689      };
  690      match ppm {
  691          PpmIdentified | PpmExpandedIdentified => {
  692              pprust::print_crate(sess.codemap(),
  693                                  sess.diagnostic(),
  694                                  &krate,
  695                                  src_name.to_strbuf(),
  696                                  &mut rdr,
  697                                  out,
  698                                  &IdentifiedAnnotation,
  699                                  is_expanded)
  700          }
  701          PpmTyped => {
  702              let ast_map = ast_map.expect("--pretty=typed missing ast_map");
  703              let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map);
  704              let annotation = TypedAnnotation {
  705                  analysis: analysis
  706              };
  707              pprust::print_crate(annotation.analysis.ty_cx.sess.codemap(),
  708                                  annotation.analysis.ty_cx.sess.diagnostic(),
  709                                  &krate,
  710                                  src_name.to_strbuf(),
  711                                  &mut rdr,
  712                                  out,
  713                                  &annotation,
  714                                  is_expanded)
  715          }
  716          _ => {
  717              pprust::print_crate(sess.codemap(),
  718                                  sess.diagnostic(),
  719                                  &krate,
  720                                  src_name.to_strbuf(),
  721                                  &mut rdr,
  722                                  out,
  723                                  &pprust::NoAnn,
  724                                  is_expanded)
  725          }
  726      }.unwrap()
  727  
  728  }
  729  
  730  pub fn get_os(triple: &str) -> Option<abi::Os> {
  731      for &(name, os) in os_names.iter() {
  732          if triple.contains(name) { return Some(os) }
  733      }
  734      None
  735  }
  736  static os_names : &'static [(&'static str, abi::Os)] = &'static [
  737      ("mingw32", abi::OsWin32),
  738      ("win32",   abi::OsWin32),
  739      ("darwin",  abi::OsMacos),
  740      ("android", abi::OsAndroid),
  741      ("linux",   abi::OsLinux),
  742      ("freebsd", abi::OsFreebsd)];
  743  
  744  pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
  745      for &(arch, abi) in architecture_abis.iter() {
  746          if triple.contains(arch) { return Some(abi) }
  747      }
  748      None
  749  }
  750  static architecture_abis : &'static [(&'static str, abi::Architecture)] = &'static [
  751      ("i386",   abi::X86),
  752      ("i486",   abi::X86),
  753      ("i586",   abi::X86),
  754      ("i686",   abi::X86),
  755      ("i786",   abi::X86),
  756  
  757      ("x86_64", abi::X86_64),
  758  
  759      ("arm",    abi::Arm),
  760      ("xscale", abi::Arm),
  761      ("thumb",  abi::Arm),
  762  
  763      ("mips",   abi::Mips)];
  764  
  765  pub fn build_target_config(sopts: &session::Options) -> session::Config {
  766      let os = match get_os(sopts.target_triple) {
  767        Some(os) => os,
  768        None => early_error("unknown operating system")
  769      };
  770      let arch = match get_arch(sopts.target_triple) {
  771        Some(arch) => arch,
  772        None => early_error("unknown architecture: " + sopts.target_triple)
  773      };
  774      let (int_type, uint_type) = match arch {
  775        abi::X86 => (ast::TyI32, ast::TyU32),
  776        abi::X86_64 => (ast::TyI64, ast::TyU64),
  777        abi::Arm => (ast::TyI32, ast::TyU32),
  778        abi::Mips => (ast::TyI32, ast::TyU32)
  779      };
  780      let target_triple = sopts.target_triple.clone();
  781      let target_strs = match arch {
  782        abi::X86 => x86::get_target_strs(target_triple, os),
  783        abi::X86_64 => x86_64::get_target_strs(target_triple, os),
  784        abi::Arm => arm::get_target_strs(target_triple, os),
  785        abi::Mips => mips::get_target_strs(target_triple, os)
  786      };
  787      session::Config {
  788          os: os,
  789          arch: arch,
  790          target_strs: target_strs,
  791          int_type: int_type,
  792          uint_type: uint_type,
  793      }
  794  }
  795  
  796  pub fn host_triple() -> &'static str {
  797      // Get the host triple out of the build environment. This ensures that our
  798      // idea of the host triple is the same as for the set of libraries we've
  799      // actually built.  We can't just take LLVM's host triple because they
  800      // normalize all ix86 architectures to i386.
  801      //
  802      // Instead of grabbing the host triple (for the current host), we grab (at
  803      // compile time) the target triple that this rustc is built with and
  804      // calling that (at runtime) the host triple.
  805      (option_env!("CFG_COMPILER_HOST_TRIPLE")).
  806          expect("CFG_COMPILER_HOST_TRIPLE")
  807  }
  808  
  809  pub fn build_session_options(matches: &getopts::Matches) -> session::Options {
  810      let mut crate_typesVec<CrateType> = Vec::new();
  811      let unparsed_crate_types = matches.opt_strs("crate-type");
  812      for unparsed_crate_type in unparsed_crate_types.iter() {
  813          for part in unparsed_crate_type.split(',') {
  814              let new_part = match part {
  815                  "lib"       => session::default_lib_output(),
  816                  "rlib"      => session::CrateTypeRlib,
  817                  "staticlib" => session::CrateTypeStaticlib,
  818                  "dylib"     => session::CrateTypeDylib,
  819                  "bin"       => session::CrateTypeExecutable,
  820                  _ => early_error(format!("unknown crate type: `{}`", part))
  821              };
  822              crate_types.push(new_part)
  823          }
  824      }
  825  
  826      let parse_only = matches.opt_present("parse-only");
  827      let no_trans = matches.opt_present("no-trans");
  828      let no_analysis = matches.opt_present("no-analysis");
  829  
  830      let lint_levels = [lint::allow, lint::warn,
  831                         lint::deny, lint::forbid];
  832      let mut lint_opts = Vec::new();
  833      let lint_dict = lint::get_lint_dict();
  834      for level in lint_levels.iter() {
  835          let level_name = lint::level_to_str(*level);
  836  
  837          let level_short = level_name.slice_chars(0, 1);
  838          let level_short = level_short.to_ascii().to_upper().into_str();
  839          let flags = matches.opt_strs(level_short).move_iter().collect::<Vec<_>>().append(
  840                                     matches.opt_strs(level_name).as_slice());
  841          for lint_name in flags.iter() {
  842              let lint_name = lint_name.replace("-", "_");
  843              match lint_dict.find_equiv(&lint_name) {
  844                None => {
  845                  early_error(format!("unknown {} flag: {}",
  846                                      level_name, lint_name));
  847                }
  848                Some(lint) => {
  849                  lint_opts.push((lint.lint, *level));
  850                }
  851              }
  852          }
  853      }
  854  
  855      let mut debugging_opts = 0;
  856      let debug_flags = matches.opt_strs("Z");
  857      let debug_map = session::debugging_opts_map();
  858      for debug_flag in debug_flags.iter() {
  859          let mut this_bit = 0;
  860          for tuple in debug_map.iter() {
  861              let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
  862              if *name == *debug_flag { this_bit = bit; break; }
  863          }
  864          if this_bit == 0 {
  865              early_error(format!("unknown debug flag: {}", *debug_flag))
  866          }
  867          debugging_opts |= this_bit;
  868      }
  869  
  870      if debugging_opts & session::DEBUG_LLVM != 0 {
  871          unsafe { llvm::LLVMSetDebug(1); }
  872      }
  873  
  874      let mut output_types = Vec::new();
  875      if !parse_only && !no_trans {
  876          let unparsed_output_types = matches.opt_strs("emit");
  877          for unparsed_output_type in unparsed_output_types.iter() {
  878              for part in unparsed_output_type.split(',') {
  879                  let output_type = match part.as_slice() {
  880                      "asm"  => link::OutputTypeAssembly,
  881                      "ir"   => link::OutputTypeLlvmAssembly,
  882                      "bc"   => link::OutputTypeBitcode,
  883                      "obj"  => link::OutputTypeObject,
  884                      "link" => link::OutputTypeExe,
  885                      _ => early_error(format!("unknown emission type: `{}`", part))
  886                  };
  887                  output_types.push(output_type)
  888              }
  889          }
  890      };
  891      output_types.as_mut_slice().sort();
  892      output_types.dedup();
  893      if output_types.len() == 0 {
  894          output_types.push(link::OutputTypeExe);
  895      }
  896  
  897      let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
  898      let target = matches.opt_str("target").unwrap_or(host_triple().to_owned());
  899      let opt_level = {
  900          if (debugging_opts & session::NO_OPT) != 0 {
  901              No
  902          } else if matches.opt_present("O") {
  903              if matches.opt_present("opt-level") {
  904                  early_error("-O and --opt-level both provided");
  905              }
  906              Default
  907          } else if matches.opt_present("opt-level") {
  908              match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) {
  909                  None      |
  910                  Some("0") => No,
  911                  Some("1") => Less,
  912                  Some("2") => Default,
  913                  Some("3") => Aggressive,
  914                  Some(arg) => {
  915                      early_error(format!("optimization level needs to be between 0-3 \
  916                                          (instead was `{}`)", arg));
  917                  }
  918              }
  919          } else {
  920              No
  921          }
  922      };
  923      let gc = debugging_opts & session::GC != 0;
  924      let debuginfo = if matches.opt_present("g") {
  925          if matches.opt_present("debuginfo") {
  926              early_error("-g and --debuginfo both provided");
  927          }
  928          FullDebugInfo
  929      } else if matches.opt_present("debuginfo") {
  930          match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) {
  931              Some("0") => NoDebugInfo,
  932              Some("1") => LimitedDebugInfo,
  933              None      |
  934              Some("2") => FullDebugInfo,
  935              Some(arg) => {
  936                  early_error(format!("optimization level needs to be between 0-3 \
  937                                      (instead was `{}`)", arg));
  938              }
  939          }
  940      } else {
  941          NoDebugInfo
  942      };
  943  
  944      let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
  945          Path::new(s.as_slice())
  946      }).collect();
  947  
  948      let cfg = parse_cfgspecs(matches.opt_strs("cfg").move_iter().collect());
  949      let test = matches.opt_present("test");
  950      let write_dependency_info = (matches.opt_present("dep-info"),
  951                                   matches.opt_str("dep-info").map(|p| Path::new(p)));
  952  
  953      let print_metas = (matches.opt_present("crate-id"),
  954                         matches.opt_present("crate-name"),
  955                         matches.opt_present("crate-file-name"));
  956      let cg = build_codegen_options(matches);
  957  
  958      session::Options {
  959          crate_types: crate_types,
  960          gc: gc,
  961          optimize: opt_level,
  962          debuginfo: debuginfo,
  963          lint_opts: lint_opts,
  964          output_types: output_types,
  965          addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
  966          maybe_sysroot: sysroot_opt,
  967          target_triple: target,
  968          cfg: cfg,
  969          test: test,
  970          parse_only: parse_only,
  971          no_trans: no_trans,
  972          no_analysis: no_analysis,
  973          debugging_opts: debugging_opts,
  974          write_dependency_info: write_dependency_info,
  975          print_metas: print_metas,
  976          cg: cg,
  977      }
  978  }
  979  
  980  pub fn build_codegen_options(matches: &getopts::Matches)
  981          -> session::CodegenOptions
  982  {
  983      let mut cg = session::basic_codegen_options();
  984      for option in matches.opt_strs("C").move_iter() {
  985          let mut iter = option.splitn('=', 1);
  986          let key = iter.next().unwrap();
  987          let value = iter.next();
  988          let option_to_lookup = key.replace("-", "_");
  989          let mut found = false;
  990          for &(candidate, setter, _) in session::CG_OPTIONS.iter() {
  991              if option_to_lookup.as_slice() != candidate { continue }
  992              if !setter(&mut cg, value) {
  993                  match value {
  994                      Some(..) => early_error(format!("codegen option `{}` takes \
  995                                                       no value", key)),
  996                      None => early_error(format!("codegen option `{0}` requires \
  997                                                   a value (-C {0}=<value>)",
  998                                                  key))
  999                  }
 1000              }
 1001              found = true;
 1002              break;
 1003          }
 1004          if !found {
 1005              early_error(format!("unknown codegen option: `{}`", key));
 1006          }
 1007      }
 1008      return cg;
 1009  }
 1010  
 1011  pub fn build_session(soptssession::Options,
 1012                       local_crate_source_fileOption<Path>)
 1013                       -> Session {
 1014      let codemap = codemap::CodeMap::new();
 1015      let diagnostic_handler =
 1016          diagnostic::default_handler();
 1017      let span_diagnostic_handler =
 1018          diagnostic::mk_span_handler(diagnostic_handler, codemap);
 1019  
 1020      build_session_(sopts, local_crate_source_file, span_diagnostic_handler)
 1021  }
 1022  
 1023  pub fn build_session_(soptssession::Options,
 1024                        local_crate_source_fileOption<Path>,
 1025                        span_diagnosticdiagnostic::SpanHandler)
 1026                        -> Session {
 1027      let target_cfg = build_target_config(&sopts);
 1028      let p_s = parse::new_parse_sess_special_handler(span_diagnostic);
 1029      let default_sysroot = match sopts.maybe_sysroot {
 1030          Some(_) => None,
 1031          None => Some(filesearch::get_or_default_sysroot())
 1032      };
 1033  
 1034      // Make the path absolute, if necessary
 1035      let local_crate_source_file = local_crate_source_file.map(|path|
 1036          if path.is_absolute() {
 1037              path.clone()
 1038          } else {
 1039              os::getcwd().join(path.clone())
 1040          }
 1041      );
 1042  
 1043      Session {
 1044          targ_cfg: target_cfg,
 1045          opts: sopts,
 1046          cstore: CStore::new(token::get_ident_interner()),
 1047          parse_sess: p_s,
 1048          // For a library crate, this is always none
 1049          entry_fn: RefCell::new(None),
 1050          entry_type: Cell::new(None),
 1051          macro_registrar_fn: Cell::new(None),
 1052          default_sysroot: default_sysroot,
 1053          local_crate_source_file: local_crate_source_file,
 1054          working_dir: os::getcwd(),
 1055          lints: RefCell::new(NodeMap::new()),
 1056          node_id: Cell::new(1),
 1057          crate_types: RefCell::new(Vec::new()),
 1058          features: front::feature_gate::Features::new(),
 1059          recursion_limit: Cell::new(64),
 1060      }
 1061  }
 1062  
 1063  pub fn parse_pretty(sess: &Session, name: &str) -> PpMode {
 1064      match name {
 1065          "normal" => PpmNormal,
 1066          "expanded" => PpmExpanded,
 1067          "typed" => PpmTyped,
 1068          "expanded,identified" => PpmExpandedIdentified,
 1069          "identified" => PpmIdentified,
 1070          _ => {
 1071              sess.fatal("argument to `pretty` must be one of `normal`, \
 1072                          `expanded`, `typed`, `identified`, \
 1073                          or `expanded,identified`");
 1074          }
 1075      }
 1076  }
 1077  
 1078  // rustc command line options
 1079  pub fn optgroups() -> Vec<getopts::OptGroup> {
 1080   vec!(
 1081    optflag("h", "help", "Display this message"),
 1082    optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
 1083    optmulti("L", "",   "Add a directory to the library search path", "PATH"),
 1084    optmulti("", "crate-type", "Comma separated list of types of crates for the compiler to emit",
 1085             "[bin|lib|rlib|dylib|staticlib]"),
 1086    optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
 1087             "[asm|bc|ir|obj|link]"),
 1088    optflag("", "crate-id", "Output the crate id and exit"),
 1089    optflag("", "crate-name", "Output the crate name and exit"),
 1090    optflag("", "crate-file-name", "Output the file(s) that would be written if compilation \
 1091            continued and exit"),
 1092    optflag("g",  "",  "Equivalent to --debuginfo=2"),
 1093    optopt("",  "debuginfo",  "Emit DWARF debug info to the objects created:
 1094           0 = no debug info,
 1095           1 = line-tables only (for stacktraces and breakpoints),
 1096           2 = full debug info with variable and type information (same as -g)", "LEVEL"),
 1097    optflag("", "no-trans", "Run all passes except translation; no output"),
 1098    optflag("", "no-analysis",
 1099            "Parse and expand the source, but run no analysis and produce no output"),
 1100    optflag("O", "", "Equivalent to --opt-level=2"),
 1101    optopt("o", "", "Write output to <filename>", "FILENAME"),
 1102    optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
 1103    optopt( "",  "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
 1104    optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
 1105    optflagopt("", "pretty",
 1106               "Pretty-print the input instead of compiling;
 1107                valid types are: normal (un-annotated source),
 1108                expanded (crates expanded),
 1109                typed (crates expanded, with type annotations),
 1110                or identified (fully parenthesized,
 1111                AST nodes and blocks with IDs)", "TYPE"),
 1112    optflagopt("", "dep-info",
 1113               "Output dependency info to <filename> after compiling, \
 1114                in a format suitable for use by Makefiles", "FILENAME"),
 1115    optopt("", "sysroot", "Override the system root", "PATH"),
 1116    optflag("", "test", "Build a test harness"),
 1117    optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
 1118                          to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
 1119                          for details)", "TRIPLE"),
 1120    optmulti("W", "warn", "Set lint warnings", "OPT"),
 1121    optmulti("A", "allow", "Set lint allowed", "OPT"),
 1122    optmulti("D", "deny", "Set lint denied", "OPT"),
 1123    optmulti("F", "forbid", "Set lint forbidden", "OPT"),
 1124    optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
 1125    optmulti("Z", "", "Set internal debugging options", "FLAG"),
 1126    optflag( "v", "version", "Print version info and exit"))
 1127  }
 1128  
 1129  pub struct OutputFilenames {
 1130      pub out_directory: Path,
 1131      pub out_filestem: ~str,
 1132      pub single_output_file: Option<Path>,
 1133  }
 1134  
 1135  impl OutputFilenames {
 1136      pub fn path(&self, flavorlink::OutputType) -> Path {
 1137          match self.single_output_file {
 1138              Some(ref path) => return path.clone(),
 1139              None => {}
 1140          }
 1141          self.temp_path(flavor)
 1142      }
 1143  
 1144      pub fn temp_path(&self, flavorlink::OutputType) -> Path {
 1145          let base = self.out_directory.join(self.out_filestem.as_slice());
 1146          match flavor {
 1147              link::OutputTypeBitcode => base.with_extension("bc"),
 1148              link::OutputTypeAssembly => base.with_extension("s"),
 1149              link::OutputTypeLlvmAssembly => base.with_extension("ll"),
 1150              link::OutputTypeObject => base.with_extension("o"),
 1151              link::OutputTypeExe => base,
 1152          }
 1153      }
 1154  
 1155      pub fn with_extension(&self, extension&str) -> Path {
 1156          let stem = self.out_filestem.as_slice();
 1157          self.out_directory.join(stem).with_extension(extension)
 1158      }
 1159  }
 1160  
 1161  pub fn build_output_filenames(input: &Input,
 1162                                odir: &Option<Path>,
 1163                                ofile: &Option<Path>,
 1164                                attrs: &[ast::Attribute],
 1165                                sess: &Session)
 1166                             -> OutputFilenames {
 1167      match *ofile {
 1168          None => {
 1169              // "-" as input file will cause the parser to read from stdin so we
 1170              // have to make up a name
 1171              // We want to toss everything after the final '.'
 1172              let dirpath = match *odir {
 1173                  Some(ref d) => d.clone(),
 1174                  None => Path::new(".")
 1175              };
 1176  
 1177              let mut stem = input.filestem();
 1178  
 1179              // If a crateid is present, we use it as the link name
 1180              let crateid = attr::find_crateid(attrs);
 1181              match crateid {
 1182                  None => {}
 1183                  Some(crateid) => stem = crateid.name.to_str(),
 1184              }
 1185              OutputFilenames {
 1186                  out_directory: dirpath,
 1187                  out_filestem: stem,
 1188                  single_output_file: None,
 1189              }
 1190          }
 1191  
 1192          Some(ref out_file) => {
 1193              let ofile = if sess.opts.output_types.len() > 1 {
 1194                  sess.warn("ignoring specified output filename because multiple \
 1195                             outputs were requested");
 1196                  None
 1197              } else {
 1198                  Some(out_file.clone())
 1199              };
 1200              if *odir != None {
 1201                  sess.warn("ignoring --out-dir flag due to -o flag.");
 1202              }
 1203              OutputFilenames {
 1204                  out_directory: out_file.dir_path(),
 1205                  out_filestem: out_file.filestem_str().unwrap().to_str(),
 1206                  single_output_file: ofile,
 1207              }
 1208          }
 1209      }
 1210  }
 1211  
 1212  pub fn early_error(msg: &str) -> ! {
 1213      let mut emitter = diagnostic::EmitterWriter::stderr();
 1214      emitter.emit(None, msg, diagnostic::Fatal);
 1215      fail!(diagnostic::FatalError);
 1216  }
 1217  
 1218  pub fn list_metadata(sess: &Session, path: &Path,
 1219                       out: &mut io::Writer) -> io::IoResult<()> {
 1220      metadata::loader::list_file_metadata(
 1221          session::sess_os_to_meta_os(sess.targ_cfg.os), path, out)
 1222  }
 1223  
 1224  #[cfg(test)]
 1225  mod test {
 1226  
 1227      use driver::driver::{build_configuration, build_session};
 1228      use driver::driver::{build_session_options, optgroups};
 1229  
 1230      use getopts::getopts;
 1231      use syntax::attr;
 1232      use syntax::attr::AttrMetaMethods;
 1233  
 1234      // When the user supplies --test we should implicitly supply --cfg test
 1235      #[test]
 1236      fn test_switch_implies_cfg_test() {
 1237          let matches =
 1238              &match getopts(["--test".to_owned()], optgroups().as_slice()) {
 1239                Ok(m) => m,
 1240                Err(f) => fail!("test_switch_implies_cfg_test: {}", f.to_err_msg())
 1241              };
 1242          let sessopts = build_session_options(matches);
 1243          let sess = build_session(sessopts, None);
 1244          let cfg = build_configuration(&sess);
 1245          assert!((attr::contains_name(cfg.as_slice(), "test")));
 1246      }
 1247  
 1248      // When the user supplies --test and --cfg test, don't implicitly add
 1249      // another --cfg test
 1250      #[test]
 1251      fn test_switch_implies_cfg_test_unless_cfg_test() {
 1252          let matches =
 1253              &match getopts(["--test".to_owned(), "--cfg=test".to_owned()],
 1254                             optgroups().as_slice()) {
 1255                Ok(m) => m,
 1256                Err(f) => {
 1257                  fail!("test_switch_implies_cfg_test_unless_cfg_test: {}",
 1258                         f.to_err_msg());
 1259                }
 1260              };
 1261          let sessopts = build_session_options(matches);
 1262          let sess = build_session(sessopts, None);
 1263          let cfg = build_configuration(&sess);
 1264          let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
 1265          assert!(test_items.next().is_some());
 1266          assert!(test_items.next().is_none());
 1267      }
 1268  }


librustc/driver/driver.rs:56:1-56:1 -enum- definition:
pub enum PpMode {
    PpmNormal,
    PpmExpanded,
references:- 4
1063: pub fn parse_pretty(sess: &Session, name: &str) -> PpMode {
1064:     match name {
librustc/lib.rs:
296:     match pretty {
297:         Some::<d::PpMode>(ppm) => {
298:             d::pretty_print_input(sess, cfg, &input, ppm, ofile);
--
300:         }
301:         None::<d::PpMode> => {/* continue */ }
302:     }


librustc/driver/driver.rs:729:1-729:1 -fn- definition:
pub fn get_os(triple: &str) -> Option<abi::Os> {
    for &(name, os) in os_names.iter() {
        if triple.contains(name) { return Some(os) }
references:- 2
765: pub fn build_target_config(sopts: &session::Options) -> session::Config {
766:     let os = match get_os(sopts.target_triple) {
767:       Some(os) => os,
librustc/metadata/creader.rs:
389:         let id_hash = link::crate_id_hash(&info.crate_id);
390:         let os = driver::get_os(driver::host_triple()).unwrap();
391:         let mut load_ctxt = loader::Context {


librustc/driver/driver.rs:169:1-169:1 -fn- definition:
pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
    -> ast::Crate {
    let krate = time(sess.time_passes(), "parsing", (), |_| {
references:- 2
661:                           ofile: Option<Path>) {
662:     let krate = phase_1_parse_input(&sess, cfg, input);
663:     let id = link::find_crate_id(krate.attrs.as_slice(), input.filestem());


librustc/driver/driver.rs:795:1-795:1 -fn- definition:
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
references:- 8
897:     let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
898:     let target = matches.opt_str("target").unwrap_or(host_triple().to_owned());
899:     let opt_level = {
librustc/driver/session.rs:
335:             self.sysroot(),
336:             host_triple(),
337:             &self.opts.addl_lib_search_paths)
--
351:         maybe_sysroot: None,
352:         target_triple: host_triple().to_owned(),
353:         cfg: Vec::new(),
librustc/metadata/creader.rs:
398:             filesearch: self.env.sess.host_filesearch(),
399:             triple: driver::host_triple(),
400:             os: session::sess_os_to_meta_os(os),
--
416:                                   only a version for triple `{}` could be found (need {})",
417:                                   info.ident, target_triple, driver::host_triple());
418:                     self.env.sess.span_err(krate.span, message);
librustc/lib.rs:
147:     println!("{} {}", argv0, vers);
148:     println!("host: {}", d::host_triple());
149: }


librustc/driver/driver.rs:116:1-116:1 -fn- definition:
pub fn append_configuration(cfg: &mut ast::CrateConfig,
                            name: InternedString) {
    if !cfg.iter().any(|mi| mi.name() == name) {
references:- 2
130:     if sess.opts.test {
131:         append_configuration(&mut user_cfg, InternedString::new("test"))
132:     }
133:     // If the user requested GC, then add the GC cfg
134:     append_configuration(&mut user_cfg, if sess.opts.gc {
135:         InternedString::new("gc")


librustc/driver/driver.rs:1128:1-1128:1 -struct- definition:
pub struct OutputFilenames {
    pub out_directory: Path,
    pub out_filestem: ~str,
references:- 13
1202:             }
1203:             OutputFilenames {
1204:                 out_directory: out_file.dir_path(),
librustc/middle/trans/base.rs:
2137:                    analysis: CrateAnalysis,
2138:                    output: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
2139:     let CrateAnalysis { ty_cx: tcx, exp_map2, reachable, .. } = analysis;
librustc/back/link.rs:
128:                       output_types: &[OutputType],
129:                       output: &OutputFilenames) {
130:         let llmod = trans.module;
--
798:                    trans: &CrateTranslation,
799:                    outputs: &OutputFilenames,
800:                    id: &CrateId) -> Vec<Path> {
--
852:                       crate_type: session::CrateType,
853:                       outputs: &OutputFilenames,
854:                       id: &CrateId) -> Path {
librustc/driver/driver.rs:
1184:             }
1185:             OutputFilenames {
1186:                 out_directory: dirpath,


librustc/driver/driver.rs:68:4-68:4 -fn- definition:
 */
pub fn anon_src() -> ~str {
    "<anon>".to_str()
references:- 3
76:         FileInput(ref ifile) => ifile.as_str().unwrap().to_str(),
77:         StrInput(_) => anon_src()
78:     }
librustc/lib.rs:
355:             parse::parse_crate_attrs_from_source_str(
356:                 d::anon_src().to_strbuf(),
357:                 src.to_strbuf(),
librustc/driver/driver.rs:
177:             StrInput(ref src) => {
178:                 parse::parse_crate_from_source_str(anon_src().to_strbuf(),
179:                                                    src.to_strbuf(),


librustc/driver/driver.rs:285:53-285:53 -fn- definition:
/// structures carrying the results of the analysis.
pub fn phase_3_run_analysis_passes(sess: Session,
                                   krate: &ast::Crate,
references:- 2
575:         let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
576:         if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
--
702:             let ast_map = ast_map.expect("--pretty=typed missing ast_map");
703:             let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map);
704:             let annotation = TypedAnnotation {


librustc/driver/driver.rs:1160:1-1160:1 -fn- definition:
pub fn build_output_filenames(input: &Input,
                              odir: &Option<Path>,
                              ofile: &Option<Path>,
references:- 2
558:             if stop_after_phase_1(&sess) { return; }
559:             let outputs = build_output_filenames(input,
560:                                                  outdir,
librustc/lib.rs:
319:         let attrs = parse_crate_attrs(&sess, &input);
320:         let t_outputs = d::build_output_filenames(&input, &odir, &ofile,
321:                                                   attrs.as_slice(), &sess);


librustc/driver/driver.rs:1211:1-1211:1 -fn- definition:
pub fn early_error(msg: &str) -> ! {
    let mut emitter = diagnostic::EmitterWriter::stderr();
    emitter.emit(None, msg, diagnostic::Fatal);
references:- 17
844:               None => {
845:                 early_error(format!("unknown {} flag: {}",
846:                                     level_name, lint_name));
--
864:         if this_bit == 0 {
865:             early_error(format!("unknown debug flag: {}", *debug_flag))
866:         }
--
993:                 match value {
994:                     Some(..) => early_error(format!("codegen option `{}` takes \
995:                                                      no value", key)),
996:                     None => early_error(format!("codegen option `{0}` requires \
997:                                                  a value (-C {0}=<value>)",
librustc/lib.rs:
235:           Err(f) => {
236:             d::early_error(f.to_err_msg());
237:           }
--
284:       }
285:       _ => d::early_error("multiple input filenames provided")
286:     };
--
310:             d::StrInput(_) => {
311:                 d::early_error("can not list metadata for stdin");
312:             }
librustc/driver/driver.rs:
1004:         if !found {
1005:             early_error(format!("unknown codegen option: `{}`", key));
1006:         }


librustc/driver/driver.rs:625:1-625:1 -struct- definition:
struct TypedAnnotation {
    analysis: CrateAnalysis,
}
references:- 2
703:             let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map);
704:             let annotation = TypedAnnotation {
705:                 analysis: analysis


librustc/driver/driver.rs:1078:30-1078:30 -fn- definition:
// rustc command line options
pub fn optgroups() -> Vec<getopts::OptGroup> {
 vec!(
references:- 2
librustc/lib.rs:
232:     let matches =
233:         &match getopts::getopts(args.as_slice(), d::optgroups().as_slice()) {
234:           Ok(m) => m,


librustc/driver/driver.rs:206:34-206:34 -fn- definition:
/// standard library and prelude.
pub fn phase_2_configure_and_expand(sess: &Session,
                                    loader: &mut CrateLoader,
references:- 2
566:                                          outputs.out_filestem);
567:             let (expanded_crate, ast_map) = phase_2_configure_and_expand(&sess, loader,
568:                                                                          krate, &id);
--
667:             let loader = &mut Loader::new(&sess);
668:             let (krate, ast_map) = phase_2_configure_and_expand(&sess, loader,
669:                                                                 krate, &id);


librustc/driver/driver.rs:152:1-152:1 -enum- definition:
pub enum Input {
    /// Load source from file
    FileInput(Path),
references:- 8
1161: pub fn build_output_filenames(input: &Input,
1162:                               odir: &Option<Path>,
librustc/lib.rs:
346: fn parse_crate_attrs(sess: &session::Session, input: &d::Input) ->
347:                      Vec<ast::Attribute> {
librustc/driver/driver.rs:
658:                           cfg: ast::CrateConfig,
659:                           input: &Input,
660:                           ppm: PpMode,


librustc/driver/driver.rs:389:1-389:1 -struct- definition:
pub struct CrateTranslation {
    pub context: ContextRef,
    pub module: ModuleRef,
references:- 12
librustc/middle/trans/base.rs:
2239:     (ccx.tcx, CrateTranslation {
2240:         context: llcx,
librustc/driver/driver.rs:
417: pub fn phase_5_run_llvm_passes(sess: &Session,
418:                                trans: &CrateTranslation,
419:                                outputs: &OutputFilenames) {
--
443: pub fn phase_6_link_output(sess: &Session,
444:                            trans: &CrateTranslation,
445:                            outputs: &OutputFilenames) {
librustc/middle/trans/base.rs:
2137:                    analysis: CrateAnalysis,
2138:                    output: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
2139:     let CrateAnalysis { ty_cx: tcx, exp_map2, reachable, .. } = analysis;
librustc/back/link.rs:
850: fn link_binary_output(sess: &Session,
851:                       trans: &CrateTranslation,
852:                       crate_type: session::CrateType,
--
1039: // links to all upstream files as well.
1040: fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
1041:                  obj_filename: &Path, out_filename: &Path) {
--
1094:              tmpdir: &Path,
1095:              trans: &CrateTranslation,
1096:              obj_filename: &Path,
--
1365:                             dylib: bool, tmpdir: &Path,
1366:                             trans: &CrateTranslation) {
1367:     // All of the heavy lifting has previously been accomplished by the


librustc/driver/driver.rs:274:1-274:1 -struct- definition:
pub struct CrateAnalysis {
    pub exp_map2: middle::resolve::ExportMap2,
    pub exported_items: middle::privacy::ExportedItems,
references:- 6
381:     CrateAnalysis {
382:         exp_map2: exp_map2,
--
626: struct TypedAnnotation {
627:     analysis: CrateAnalysis,
628: }
librustc/middle/trans/base.rs:
2138:                    output: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
2139:     let CrateAnalysis { ty_cx: tcx, exp_map2, reachable, .. } = analysis;