use driver::session;
use front;
use lib::llvm::llvm;
+use lib::llvm::{ContextRef, ModuleRef};
+use metadata::common::LinkMeta;
use metadata::{creader, cstore, filesearch};
use metadata;
use middle::{trans, freevars, kind, ty, typeck, lint, astencode, reachable};
use util::common::time;
use util::ppaux;
-use std::hashmap::HashMap;
+use std::hashmap::{HashMap,HashSet};
use std::int;
use std::io;
use std::os;
}
pub fn default_configuration(sess: Session, argv0: @str, input: &input) ->
- ast::crate_cfg {
+ ast::CrateConfig {
let (libc, tos) = match sess.targ_cfg.os {
session::os_win32 => (@"msvcrt.dll", @"win32"),
session::os_macos => (@"libc.dylib", @"macos"),
mk(@"build_input", source_name(input))];
}
-pub fn append_configuration(cfg: &mut ast::crate_cfg, name: @str) {
+pub fn append_configuration(cfg: &mut ast::CrateConfig, name: @str) {
if !cfg.iter().any(|mi| mi.name() == name) {
cfg.push(attr::mk_word_item(name))
}
}
pub fn build_configuration(sess: Session, argv0: @str, input: &input) ->
- ast::crate_cfg {
+ ast::CrateConfig {
// Combine the configuration requested by the session (command line) with
// some default and generated configuration items
let default_cfg = default_configuration(sess, argv0, input);
// Convert strings provided as --cfg [cfgspec] into a crate_cfg
fn parse_cfgspecs(cfgspecs: ~[~str],
- demitter: diagnostic::Emitter) -> ast::crate_cfg {
+ demitter: diagnostic::Emitter) -> ast::CrateConfig {
do cfgspecs.consume_iter().transform |s| {
let sess = parse::new_parse_sess(Some(demitter));
parse::parse_meta_from_source_str(@"cfgspec", s.to_managed(), ~[], sess)
- }.collect::<ast::crate_cfg>()
+ }.collect::<ast::CrateConfig>()
}
pub enum input {
str_input(@str)
}
-pub fn parse_input(sess: Session, cfg: ast::crate_cfg, input: &input)
- -> @ast::crate {
- match *input {
- file_input(ref file) => {
- parse::parse_crate_from_file(&(*file), cfg, sess.parse_sess)
- }
- str_input(src) => {
- parse::parse_crate_from_source_str(
- anon_src(), src, cfg, sess.parse_sess)
- }
- }
-}
-
-/// First phase to do, last phase to do
-#[deriving(Eq)]
-pub struct compile_upto {
- from: compile_phase,
- to: compile_phase
-}
-
-#[deriving(Eq)]
-pub enum compile_phase {
- cu_parse,
- cu_expand, // means "it's already expanded"
- cu_typeck,
- cu_no_trans,
- cu_everything,
+pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, input: &input)
+ -> @ast::Crate {
+ time(sess.time_passes(), ~"parsing", || {
+ match *input {
+ file_input(ref file) => {
+ parse::parse_crate_from_file(&(*file), cfg.clone(), sess.parse_sess)
+ }
+ str_input(src) => {
+ parse::parse_crate_from_source_str(
+ anon_src(), src, cfg.clone(), sess.parse_sess)
+ }
+ }
+ })
}
// For continuing compilation after a parsed crate has been
// modified
-
-#[fixed_stack_segment]
-pub fn compile_rest(sess: Session,
- cfg: ast::crate_cfg,
- phases: compile_upto,
- outputs: Option<@OutputFilenames>,
- curr: Option<@ast::crate>)
- -> (Option<@ast::crate>, Option<ty::ctxt>) {
-
+/// Run the "early phases" of the compiler: initial `cfg` processing,
+/// syntax expansion, secondary `cfg` expansion, synthesis of a test
+/// harness if one is to be provided and injection of a dependency on the
+/// standard library and prelude.
+pub fn phase_2_configure_and_expand(sess: Session,
+ cfg: ast::CrateConfig,
+ mut crate: @ast::Crate) -> @ast::Crate {
let time_passes = sess.time_passes();
- let mut crate = curr.unwrap();
-
- if phases.from == cu_parse || phases.from == cu_everything {
+ *sess.building_library = session::building_library(sess.opts.crate_type,
+ crate, sess.opts.test);
- *sess.building_library = session::building_library(
- sess.opts.crate_type, crate, sess.opts.test);
- // strip before expansion to allow macros to depend on
- // configuration variables e.g/ in
- //
- // #[macro_escape] #[cfg(foo)]
- // mod bar { macro_rules! baz!(() => {{}}) }
- //
- // baz! should not use this definition unless foo is enabled.
- crate = time(time_passes, ~"std macros injection", ||
- syntax::ext::expand::inject_std_macros(sess.parse_sess,
- cfg.clone(),
- crate));
+ // strip before expansion to allow macros to depend on
+ // configuration variables e.g/ in
+ //
+ // #[macro_escape] #[cfg(foo)]
+ // mod bar { macro_rules! baz!(() => {{}}) }
+ //
+ // baz! should not use this definition unless foo is enabled.
+ crate = time(time_passes, ~"std macros injection", ||
+ syntax::ext::expand::inject_std_macros(sess.parse_sess,
+ cfg.clone(),
+ crate));
- crate = time(time_passes, ~"configuration 1", ||
- front::config::strip_unconfigured_items(crate));
+ crate = time(time_passes, ~"configuration 1", ||
+ front::config::strip_unconfigured_items(crate));
- crate = time(time_passes, ~"expansion", ||
- syntax::ext::expand::expand_crate(sess.parse_sess,
- cfg.clone(),
- crate));
+ crate = time(time_passes, ~"expansion", ||
+ syntax::ext::expand::expand_crate(sess.parse_sess, cfg.clone(),
+ crate));
- // strip again, in case expansion added anything with a #[cfg].
- crate = time(time_passes, ~"configuration 2", ||
- front::config::strip_unconfigured_items(crate));
+ // strip again, in case expansion added anything with a #[cfg].
+ crate = time(time_passes, ~"configuration 2", ||
+ front::config::strip_unconfigured_items(crate));
+ crate = time(time_passes, ~"maybe building test harness", ||
+ front::test::modify_for_testing(sess, crate));
- crate = time(time_passes, ~"maybe building test harness", ||
- front::test::modify_for_testing(sess, crate));
- }
+ crate = time(time_passes, ~"std injection", ||
+ front::std_inject::maybe_inject_libstd_ref(sess, crate));
- if phases.to == cu_expand {
- return (Some(crate), None);
- }
+ return crate;
+}
- assert!(phases.from != cu_no_trans);
+pub struct CrateAnalysis {
+ exp_map2: middle::resolve::ExportMap2,
+ ty_cx: ty::ctxt,
+ maps: astencode::Maps,
+ reachable: @mut HashSet<ast::NodeId>
+}
- let (llcx, llmod, link_meta) = {
- crate = time(time_passes, ~"std injection", ||
- front::std_inject::maybe_inject_libstd_ref(sess, crate));
+/// Run the resolution, typechecking, region checking and other
+/// miscellaneous analysis passes on the crate. Return various
+/// structures carrying the results of the analysis.
+pub fn phase_3_run_analysis_passes(sess: Session,
+ crate: @ast::Crate) -> CrateAnalysis {
- let ast_map = time(time_passes, ~"ast indexing", ||
- syntax::ast_map::map_crate(sess.diagnostic(), crate));
+ let time_passes = sess.time_passes();
+ let ast_map = time(time_passes, ~"ast indexing", ||
+ syntax::ast_map::map_crate(sess.diagnostic(), crate));
- time(time_passes, ~"external crate/lib resolution", ||
- creader::read_crates(sess.diagnostic(), crate, sess.cstore,
- sess.filesearch,
- session::sess_os_to_meta_os(sess.targ_cfg.os),
- sess.opts.is_static,
- token::get_ident_interner()));
+ time(time_passes, ~"external crate/lib resolution", ||
+ creader::read_crates(sess.diagnostic(), crate, sess.cstore,
+ sess.filesearch,
+ session::sess_os_to_meta_os(sess.targ_cfg.os),
+ sess.opts.is_static,
+ token::get_ident_interner()));
- let lang_items = time(time_passes, ~"language item collection", ||
- middle::lang_items::collect_language_items(crate, sess));
+ let lang_items = time(time_passes, ~"language item collection", ||
+ middle::lang_items::collect_language_items(crate, sess));
- let middle::resolve::CrateMap {
- def_map: def_map,
- exp_map2: exp_map2,
- trait_map: trait_map
- } =
- time(time_passes, ~"resolution", ||
- middle::resolve::resolve_crate(sess, lang_items, crate));
+ let middle::resolve::CrateMap {
+ def_map: def_map,
+ exp_map2: exp_map2,
+ trait_map: trait_map
+ } =
+ time(time_passes, ~"resolution", ||
+ middle::resolve::resolve_crate(sess, lang_items, crate));
- time(time_passes, ~"looking for entry point",
- || middle::entry::find_entry_point(sess, crate, ast_map));
+ time(time_passes, ~"looking for entry point",
+ || middle::entry::find_entry_point(sess, crate, ast_map));
- let freevars = time(time_passes, ~"freevar finding", ||
- freevars::annotate_freevars(def_map, crate));
+ let freevars = time(time_passes, ~"freevar finding", ||
+ freevars::annotate_freevars(def_map, crate));
- let region_map = time(time_passes, ~"region resolution", ||
- middle::region::resolve_crate(sess, def_map, crate));
+ let region_map = time(time_passes, ~"region resolution", ||
+ middle::region::resolve_crate(sess, def_map, crate));
- let rp_set = time(time_passes, ~"region parameterization inference", ||
- middle::region::determine_rp_in_crate(sess, ast_map, def_map, crate));
+ let rp_set = time(time_passes, ~"region parameterization inference", ||
+ middle::region::determine_rp_in_crate(sess, ast_map, def_map, crate));
- let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
- region_map, rp_set, lang_items);
+ let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
+ region_map, rp_set, lang_items);
- // passes are timed inside typeck
- let (method_map, vtable_map) = typeck::check_crate(
- ty_cx, trait_map, crate);
+ // passes are timed inside typeck
+ let (method_map, vtable_map) = typeck::check_crate(
+ ty_cx, trait_map, crate);
- // These next two const passes can probably be merged
- time(time_passes, ~"const marking", ||
- middle::const_eval::process_crate(crate, ty_cx));
+ // These next two const passes can probably be merged
+ time(time_passes, ~"const marking", ||
+ middle::const_eval::process_crate(crate, ty_cx));
- time(time_passes, ~"const checking", ||
- middle::check_const::check_crate(sess, crate, ast_map, def_map,
- method_map, ty_cx));
+ time(time_passes, ~"const checking", ||
+ middle::check_const::check_crate(sess, crate, ast_map, def_map,
+ method_map, ty_cx));
- if phases.to == cu_typeck { return (Some(crate), Some(ty_cx)); }
+ time(time_passes, ~"privacy checking", ||
+ middle::privacy::check_crate(ty_cx, &method_map, crate));
- time(time_passes, ~"privacy checking", ||
- middle::privacy::check_crate(ty_cx, &method_map, crate));
+ time(time_passes, ~"effect checking", ||
+ middle::effect::check_crate(ty_cx, method_map, crate));
- time(time_passes, ~"effect checking", ||
- middle::effect::check_crate(ty_cx, method_map, crate));
+ time(time_passes, ~"loop checking", ||
+ middle::check_loop::check_crate(ty_cx, crate));
- time(time_passes, ~"loop checking", ||
- middle::check_loop::check_crate(ty_cx, crate));
+ let middle::moves::MoveMaps {moves_map, moved_variables_set,
+ capture_map} =
+ time(time_passes, ~"compute moves", ||
+ middle::moves::compute_moves(ty_cx, method_map, crate));
- let middle::moves::MoveMaps {moves_map, moved_variables_set,
- capture_map} =
- time(time_passes, ~"compute moves", ||
- middle::moves::compute_moves(ty_cx, method_map, crate));
+ time(time_passes, ~"match checking", ||
+ middle::check_match::check_crate(ty_cx, method_map,
+ moves_map, crate));
- time(time_passes, ~"match checking", ||
- middle::check_match::check_crate(ty_cx, method_map,
- moves_map, crate));
+ time(time_passes, ~"liveness checking", ||
+ middle::liveness::check_crate(ty_cx, method_map,
+ capture_map, crate));
- time(time_passes, ~"liveness checking", ||
- middle::liveness::check_crate(ty_cx, method_map,
+ let (root_map, write_guard_map) =
+ time(time_passes, ~"borrow checking", ||
+ middle::borrowck::check_crate(ty_cx, method_map,
+ moves_map, moved_variables_set,
capture_map, crate));
- let (root_map, write_guard_map) =
- time(time_passes, ~"borrow checking", ||
- middle::borrowck::check_crate(ty_cx, method_map,
- moves_map, moved_variables_set,
- capture_map, crate));
-
- time(time_passes, ~"kind checking", ||
- kind::check_crate(ty_cx, method_map, crate));
+ time(time_passes, ~"kind checking", ||
+ kind::check_crate(ty_cx, method_map, crate));
- let reachable_map =
- time(time_passes, ~"reachability checking", ||
- reachable::find_reachable(ty_cx, method_map, crate));
+ let reachable_map =
+ time(time_passes, ~"reachability checking", ||
+ reachable::find_reachable(ty_cx, method_map, crate));
- time(time_passes, ~"lint checking", ||
- lint::check_crate(ty_cx, crate));
+ time(time_passes, ~"lint checking", ||
+ lint::check_crate(ty_cx, crate));
- if phases.to == cu_no_trans {
- return (Some(crate), Some(ty_cx));
- }
-
- let maps = astencode::Maps {
+ CrateAnalysis {
+ exp_map2: exp_map2,
+ ty_cx: ty_cx,
+ maps: astencode::Maps {
root_map: root_map,
method_map: method_map,
vtable_map: vtable_map,
write_guard_map: write_guard_map,
capture_map: capture_map
- };
+ },
+ reachable: reachable_map
+ }
+}
- let outputs = outputs.get_ref();
- time(time_passes, ~"translation", ||
- trans::base::trans_crate(sess,
- crate,
- ty_cx,
- &outputs.obj_filename,
- exp_map2,
- reachable_map,
- maps))
- };
+pub struct CrateTranslation {
+ context: ContextRef,
+ module: ModuleRef,
+ link: LinkMeta
+}
- let outputs = outputs.get_ref();
- if (sess.opts.debugging_opts & session::print_link_args) != 0 {
- io::println(link::link_args(sess, &outputs.obj_filename,
- &outputs.out_filename, link_meta).connect(" "));
- }
+/// Run the translation phase to LLVM, after which the AST and analysis can
+/// be discarded.
+pub fn phase_4_translate_to_llvm(sess: Session,
+ crate: @ast::Crate,
+ analysis: &CrateAnalysis,
+ outputs: &OutputFilenames) -> CrateTranslation {
+ time(sess.time_passes(), ~"translation", ||
+ trans::base::trans_crate(sess, crate, analysis,
+ &outputs.obj_filename))
+}
+
+/// Run LLVM itself, producing a bitcode file, assembly file or object file
+/// as a side effect.
+pub fn phase_5_run_llvm_passes(sess: Session,
+ trans: &CrateTranslation,
+ outputs: &OutputFilenames) {
// NB: Android hack
- if sess.targ_cfg.arch == abi::Arm &&
- (sess.opts.output_type == link::output_type_object ||
- sess.opts.output_type == link::output_type_exe) {
+ if sess.targ_cfg.os == session::os_android &&
+ (sess.opts.output_type == link::output_type_object ||
+ sess.opts.output_type == link::output_type_exe) {
let output_type = link::output_type_assembly;
let obj_filename = outputs.obj_filename.with_filetype("s");
- time(time_passes, ~"LLVM passes", ||
- link::write::run_passes(sess, llcx, llmod, output_type,
+ time(sess.time_passes(), ~"LLVM passes", ||
+ link::write::run_passes(sess,
+ trans.context,
+ trans.module,
+ output_type,
&obj_filename));
link::write::run_ndk(sess, &obj_filename, &outputs.obj_filename);
} else {
- time(time_passes, ~"LLVM passes", ||
- link::write::run_passes(sess, llcx, llmod, sess.opts.output_type,
+ time(sess.time_passes(), ~"LLVM passes", ||
+ link::write::run_passes(sess,
+ trans.context,
+ trans.module,
+ sess.opts.output_type,
&outputs.obj_filename));
}
+}
- let stop_after_codegen =
- sess.opts.output_type != link::output_type_exe ||
- (sess.opts.is_static && *sess.building_library) ||
- sess.opts.jit;
-
- if stop_after_codegen { return (None, None); }
-
- time(time_passes, ~"linking", ||
+/// Run the linker on any artifacts that resulted from the LLVM run.
+/// This should produce either a finished executable or library.
+pub fn phase_6_link_output(sess: Session,
+ trans: &CrateTranslation,
+ outputs: &OutputFilenames) {
+ time(sess.time_passes(), ~"linking", ||
link::link_binary(sess,
&outputs.obj_filename,
- &outputs.out_filename, link_meta));
+ &outputs.out_filename,
+ trans.link));
+}
- return (None, None);
+pub fn stop_after_phase_3(sess: Session) -> bool {
+ if sess.opts.no_trans {
+ debug!("invoked with --no-trans, returning early from compile_input");
+ return true;
+ }
+ return false;
}
-pub fn compile_upto(sess: Session,
- cfg: ast::crate_cfg,
- input: &input,
- upto: compile_phase,
- outputs: Option<@OutputFilenames>)
- -> (Option<@ast::crate>, Option<ty::ctxt>) {
- let time_passes = sess.time_passes();
- let crate = time(time_passes,
- ~"parsing",
- || parse_input(sess, cfg.clone(), input) );
- if upto == cu_parse {
- return (Some(crate), None);
+pub fn stop_after_phase_1(sess: Session) -> bool {
+ if sess.opts.parse_only {
+ debug!("invoked with --parse-only, returning early from compile_input");
+ return true;
+ }
+ return false;
+}
+
+pub fn stop_after_phase_5(sess: Session) -> bool {
+ if sess.opts.output_type != link::output_type_exe {
+ debug!("not building executable, returning early from compile_input");
+ return true;
+ }
+
+ if sess.opts.is_static && *sess.building_library {
+ debug!("building static library, returning early from compile_input");
+ return true;
}
- compile_rest(sess,
- cfg,
- compile_upto {
- from: cu_parse,
- to: upto
- },
- outputs,
- Some(crate))
+ if sess.opts.jit {
+ debug!("running JIT, returning early from compile_input");
+ return true;
+ }
+ return false;
}
-pub fn compile_input(sess: Session, cfg: ast::crate_cfg, input: &input,
+#[fixed_stack_segment]
+pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &input,
outdir: &Option<Path>, output: &Option<Path>) {
- let upto = if sess.opts.parse_only { cu_parse }
- else if sess.opts.no_trans { cu_no_trans }
- else { cu_everything };
- let outputs = build_output_filenames(input, outdir, output, [], sess); // ???
- compile_upto(sess, cfg, input, upto, Some(outputs));
+ // 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) = {
+ let expanded_crate = {
+ let crate = phase_1_parse_input(sess, cfg.clone(), input);
+ if stop_after_phase_1(sess) { return; }
+ phase_2_configure_and_expand(sess, cfg, crate)
+ };
+ let analysis = phase_3_run_analysis_passes(sess, expanded_crate);
+ if stop_after_phase_3(sess) { return; }
+ let outputs = build_output_filenames(input, outdir, output, [], sess);
+ let trans = phase_4_translate_to_llvm(sess, expanded_crate,
+ &analysis, outputs);
+ (outputs, trans)
+ };
+ phase_5_run_llvm_passes(sess, &trans, outputs);
+ if stop_after_phase_5(sess) { return; }
+ phase_6_link_output(sess, &trans, outputs);
}
-pub fn pretty_print_input(sess: Session, cfg: ast::crate_cfg, input: &input,
+pub fn pretty_print_input(sess: Session, cfg: ast::CrateConfig, input: &input,
ppm: pp_mode) {
+
fn ann_paren_for_expr(node: pprust::ann_node) {
match node {
pprust::node_expr(s, _) => pprust::popen(s),
}
}
- // Because the pretty printer needs to make a pass over the source
- // to collect comments and literals, and we need to support reading
- // from stdin, we're going to just suck the source into a string
- // so both the parser and pretty-printer can use it.
- let upto = match ppm {
- ppm_expanded | ppm_expanded_identified => cu_expand,
- ppm_typed => cu_typeck,
- _ => cu_parse
+ let crate = phase_1_parse_input(sess, cfg.clone(), input);
+
+ let (crate, is_expanded) = match ppm {
+ ppm_expanded | ppm_expanded_identified | ppm_typed => {
+ (phase_2_configure_and_expand(sess, cfg, crate), true)
+ }
+ _ => (crate, false)
};
- let (crate, tcx) = compile_upto(sess, cfg, input, upto, None);
- let ann = match ppm {
- ppm_typed => {
- pprust::pp_ann {pre: ann_paren_for_expr,
- post: |a| ann_typed_post(tcx.get(), a) }
- }
- ppm_identified | ppm_expanded_identified => {
- pprust::pp_ann {pre: ann_paren_for_expr,
- post: ann_identified_post}
- }
- ppm_expanded | ppm_normal => {
- pprust::no_ann()
- }
+ let annotation = match ppm {
+ ppm_identified | ppm_expanded_identified => {
+ pprust::pp_ann {
+ pre: ann_paren_for_expr,
+ post: ann_identified_post
+ }
+ }
+ ppm_typed => {
+ let analysis = phase_3_run_analysis_passes(sess, crate);
+ pprust::pp_ann {
+ pre: ann_paren_for_expr,
+ post: |a| ann_typed_post(analysis.ty_cx, a)
+ }
+ }
+ _ => pprust::no_ann()
};
- let is_expanded = upto != cu_parse;
+
let src = sess.codemap.get_filemap(source_name(input)).src;
do io::with_str_reader(src) |rdr| {
pprust::print_crate(sess.codemap, token::get_ident_interner(),
- sess.span_diagnostic, crate.unwrap(),
+ sess.span_diagnostic, crate,
source_name(input),
- rdr, io::stdout(), ann, is_expanded);
+ rdr, io::stdout(),
+ annotation, is_expanded);
}
}
pub fn get_os(triple: &str) -> Option<session::os> {
- for os_names.iter().advance |&(name, os)| {
+ for &(name, os) in os_names.iter() {
if triple.contains(name) { return Some(os) }
}
None
("freebsd", session::os_freebsd)];
pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
- for architecture_abis.iter().advance |&(arch, abi)| {
+ for &(arch, abi) in architecture_abis.iter() {
if triple.contains(arch) { return Some(abi) }
}
None
lint::deny, lint::forbid];
let mut lint_opts = ~[];
let lint_dict = lint::get_lint_dict();
- for lint_levels.iter().advance |level| {
+ for level in lint_levels.iter() {
let level_name = lint::level_to_str(*level);
// FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
let level_short = level_short.to_ascii().to_upper().to_str_ascii();
let flags = vec::append(getopts::opt_strs(matches, level_short),
getopts::opt_strs(matches, level_name));
- for flags.iter().advance |lint_name| {
+ for lint_name in flags.iter() {
let lint_name = lint_name.replace("-", "_");
match lint_dict.find_equiv(&lint_name) {
None => {
let mut debugging_opts = 0u;
let debug_flags = getopts::opt_strs(matches, "Z");
let debug_map = session::debugging_opts_map();
- for debug_flags.iter().advance |debug_flag| {
+ for debug_flag in debug_flags.iter() {
let mut this_bit = 0u;
- for debug_map.iter().advance |tuple| {
+ for tuple in debug_map.iter() {
let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
if name == debug_flag { this_bit = bit; break; }
}
} else if opt_present(matches, "emit-llvm") {
link::output_type_bitcode
} else { link::output_type_exe };
- let sysroot_opt = getopts::opt_maybe_str(matches, "sysroot");
- let sysroot_opt = sysroot_opt.map(|m| @Path(*m));
+ let sysroot_opt = getopts::opt_maybe_str(matches, "sysroot").map_move(|m| @Path(m));
let target_opt = getopts::opt_maybe_str(matches, "target");
let target_feature_opt = getopts::opt_maybe_str(matches, "target-feature");
let save_temps = getopts::opt_present(matches, "save-temps");
optmulti("", "cfg", "Configure the compilation
environment", "SPEC"),
optflag("", "emit-llvm",
- "Produce an LLVM bitcode file"),
+ "Produce an LLVM assembly file if used with -S option;
+ produce an LLVM bitcode file otherwise"),
optflag("h", "help","Display this message"),
optmulti("L", "", "Add a directory to the library search path",
"PATH"),
ofile: &Option<Path>,
attrs: &[ast::Attribute],
sess: Session)
- -> @OutputFilenames {
+ -> ~OutputFilenames {
let obj_path;
let out_path;
let sopts = sess.opts;
};
let mut stem = match *input {
- file_input(ref ifile) => (*ifile).filestem().get().to_managed(),
+ file_input(ref ifile) => (*ifile).filestem().unwrap().to_managed(),
str_input(_) => @"rust_out"
};
};
if *sess.building_library {
- // FIXME (#2401): We might want to warn here; we're actually not
- // going to respect the user's choice of library name when it
- // comes time to link, we'll be linking to
- // lib<basename>-<hash>-<version>.so no matter what.
+ sess.warn("ignoring specified output filename for library.");
}
if *odir != None {
}
}
- @OutputFilenames {
+ ~OutputFilenames {
out_filename: out_path,
obj_filename: obj_path
}