auto merge of #8077 : graydon/rust/reorganize-driver, r=pcwalton

The purpose here is to get rid of compile_upto, which pretty much always requires the user to read the source to figure out what it does. It's replaced by a sequence of obviously-named functions:

  - phase_1_parse_input(sess, cfg, input);
  - phase_2_configure_and_expand(sess, cfg, crate);
  - phase_3_run_analysis_passes(sess, expanded_crate);
  - phase_4_translate_to_llvm(sess, expanded_crate, &analysis, outputs);
  - phase_5_run_llvm_passes(sess, &trans, outputs);
  - phase_6_link_output(sess, &trans, outputs); 

Each of which takes what it takes and returns what it returns, with as little variation as possible in behaviour: no "pairs of options" and "pairs of control flags". You can tell if you missed a phase because you will be missing a `phase_N` call to some `N` between 1 and 6.

It does mean that people invoking librustc from outside need to write more function calls. The benefit is that they can _figure out what they're doing_ much more easily, and stop at any point, rather than further overloading the tangled logic of `compile_upto`.
This commit is contained in:
bors 2013-07-27 14:49:28 -07:00
commit 098106870e
5 changed files with 300 additions and 287 deletions

View File

@ -16,6 +16,8 @@
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};
@ -23,7 +25,7 @@
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;
@ -132,280 +134,295 @@ pub enum input {
str_input(@str)
}
pub fn parse_input(sess: Session, cfg: ast::CrateConfig, input: &input)
pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, 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,
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::CrateConfig,
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);
// 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, ~"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));
*sess.building_library = session::building_library(sess.opts.crate_type,
crate, sess.opts.test);
crate = time(time_passes, ~"maybe building test harness", ||
front::test::modify_for_testing(sess, 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));
if phases.to == cu_expand {
return (Some(crate), None);
}
crate = time(time_passes, ~"configuration 1", ||
front::config::strip_unconfigured_items(crate));
assert!(phases.from != cu_no_trans);
crate = time(time_passes, ~"expansion", ||
syntax::ext::expand::expand_crate(sess.parse_sess, cfg.clone(),
crate));
let (llcx, llmod, link_meta) = {
crate = time(time_passes, ~"std injection", ||
front::std_inject::maybe_inject_libstd_ref(sess, crate));
// strip again, in case expansion added anything with a #[cfg].
crate = time(time_passes, ~"configuration 2", ||
front::config::strip_unconfigured_items(crate));
let ast_map = time(time_passes, ~"ast indexing", ||
syntax::ast_map::map_crate(sess.diagnostic(), crate));
crate = time(time_passes, ~"maybe building test harness", ||
front::test::modify_for_testing(sess, 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()));
crate = time(time_passes, ~"std injection", ||
front::std_inject::maybe_inject_libstd_ref(sess, crate));
let lang_items = time(time_passes, ~"language item collection", ||
middle::lang_items::collect_language_items(crate, sess));
return 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));
pub struct CrateAnalysis {
exp_map2: middle::resolve::ExportMap2,
ty_cx: ty::ctxt,
maps: astencode::Maps,
reachable: @mut HashSet<ast::node_id>
}
time(time_passes, ~"looking for entry point",
|| middle::entry::find_entry_point(sess, crate, ast_map));
/// 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 freevars = time(time_passes, ~"freevar finding", ||
freevars::annotate_freevars(def_map, crate));
let time_passes = sess.time_passes();
let ast_map = time(time_passes, ~"ast indexing", ||
syntax::ast_map::map_crate(sess.diagnostic(), crate));
let region_map = time(time_passes, ~"region resolution", ||
middle::region::resolve_crate(sess, def_map, 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()));
let rp_set = time(time_passes, ~"region parameterization inference", ||
middle::region::determine_rp_in_crate(sess, ast_map, def_map, crate));
let lang_items = time(time_passes, ~"language item collection", ||
middle::lang_items::collect_language_items(crate, sess));
let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
region_map, rp_set, lang_items);
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));
// passes are timed inside typeck
let (method_map, vtable_map) = typeck::check_crate(
ty_cx, trait_map, crate);
time(time_passes, ~"looking for entry point",
|| middle::entry::find_entry_point(sess, crate, ast_map));
// These next two const passes can probably be merged
time(time_passes, ~"const marking", ||
middle::const_eval::process_crate(crate, ty_cx));
let freevars = time(time_passes, ~"freevar finding", ||
freevars::annotate_freevars(def_map, crate));
time(time_passes, ~"const checking", ||
middle::check_const::check_crate(sess, crate, ast_map, def_map,
method_map, ty_cx));
let region_map = time(time_passes, ~"region resolution", ||
middle::region::resolve_crate(sess, def_map, crate));
if phases.to == cu_typeck { return (Some(crate), Some(ty_cx)); }
let rp_set = time(time_passes, ~"region parameterization inference", ||
middle::region::determine_rp_in_crate(sess, ast_map, def_map, crate));
time(time_passes, ~"privacy checking", ||
middle::privacy::check_crate(ty_cx, &method_map, crate));
let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
region_map, rp_set, lang_items);
time(time_passes, ~"effect checking", ||
middle::effect::check_crate(ty_cx, method_map, crate));
// passes are timed inside typeck
let (method_map, vtable_map) = typeck::check_crate(
ty_cx, trait_map, crate);
time(time_passes, ~"loop checking", ||
middle::check_loop::check_crate(ty_cx, crate));
// These next two const passes can probably be merged
time(time_passes, ~"const marking", ||
middle::const_eval::process_crate(crate, ty_cx));
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, ~"const checking", ||
middle::check_const::check_crate(sess, crate, ast_map, def_map,
method_map, ty_cx));
time(time_passes, ~"match checking", ||
middle::check_match::check_crate(ty_cx, method_map,
moves_map, crate));
time(time_passes, ~"privacy checking", ||
middle::privacy::check_crate(ty_cx, &method_map, crate));
time(time_passes, ~"liveness checking", ||
middle::liveness::check_crate(ty_cx, method_map,
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));
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, ~"liveness checking", ||
middle::liveness::check_crate(ty_cx, method_map,
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));
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
};
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))
};
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(" "));
},
reachable: reachable_map
}
}
pub struct CrateTranslation {
context: ContextRef,
module: ModuleRef,
link: LinkMeta
}
/// 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) {
(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));
return (None, None);
&outputs.out_filename,
trans.link));
}
pub fn compile_upto(sess: Session,
cfg: ast::CrateConfig,
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_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 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;
}
compile_rest(sess,
cfg,
compile_upto {
from: cu_parse,
to: upto
},
outputs,
Some(crate))
if sess.opts.is_static && *sess.building_library {
debug!("building static library, returning early from compile_input");
return true;
}
if sess.opts.jit {
debug!("running JIT, returning early from compile_input");
return true;
}
return false;
}
#[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));
let outputs = build_output_filenames(input, outdir, output, [], sess);
let crate = phase_1_parse_input(sess, cfg.clone(), input);
if stop_after_phase_1(sess) { return; }
let expanded_crate = 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 trans = phase_4_translate_to_llvm(sess, expanded_crate, &analysis, outputs);
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::CrateConfig, input: &input,
ppm: pp_mode) {
fn ann_paren_for_expr(node: pprust::ann_node) {
match node {
pprust::node_expr(s, _) => pprust::popen(s),
@ -447,37 +464,39 @@ fn ann_identified_post(node: pprust::ann_node) {
}
}
// 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, tcx) = compile_upto(sess, cfg, input, upto, None);
let crate = phase_1_parse_input(sess, cfg.clone(), input);
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 (crate, is_expanded) = match ppm {
ppm_expanded | ppm_expanded_identified | ppm_typed => {
(phase_2_configure_and_expand(sess, cfg, crate), true)
}
_ => (crate, false)
};
let is_expanded = upto != cu_parse;
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 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);
}
}
@ -864,7 +883,7 @@ pub fn build_output_filenames(input: &input,
ofile: &Option<Path>,
attrs: &[ast::Attribute],
sess: Session)
-> @OutputFilenames {
-> ~OutputFilenames {
let obj_path;
let out_path;
let sopts = sess.opts;
@ -943,7 +962,7 @@ pub fn build_output_filenames(input: &input,
}
}
@OutputFilenames {
~OutputFilenames {
out_filename: out_path,
obj_filename: obj_path
}

View File

@ -28,7 +28,8 @@
use back::{link, abi};
use driver::session;
use driver::session::Session;
use lib::llvm::{ContextRef, ModuleRef, ValueRef, BasicBlockRef};
use driver::driver::{CrateAnalysis, CrateTranslation};
use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
use lib::llvm::{llvm, True};
use lib;
use metadata::common::LinkMeta;
@ -36,7 +37,6 @@
use middle::astencode;
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
use middle::lang_items::{MallocFnLangItem, ClosureExchangeMallocFnLangItem};
use middle::resolve;
use middle::trans::_match;
use middle::trans::adt;
use middle::trans::base;
@ -66,7 +66,7 @@
use middle::trans::type_::Type;
use std::hash;
use std::hashmap::{HashMap, HashSet};
use std::hashmap::HashMap;
use std::io;
use std::libc::c_uint;
use std::uint;
@ -2970,12 +2970,8 @@ pub fn write_abi_version(ccx: &mut CrateContext) {
pub fn trans_crate(sess: session::Session,
crate: &ast::Crate,
tcx: ty::ctxt,
output: &Path,
emap2: resolve::ExportMap2,
reachable_map: @mut HashSet<ast::node_id>,
maps: astencode::Maps)
-> (ContextRef, ModuleRef, LinkMeta) {
analysis: &CrateAnalysis,
output: &Path) -> CrateTranslation {
// Before we touch LLVM, make sure that multithreading is enabled.
if unsafe { !llvm::LLVMRustStartMultithreading() } {
//sess.bug("couldn't enable multi-threaded LLVM");
@ -2996,12 +2992,12 @@ pub fn trans_crate(sess: session::Session,
let ccx = @mut CrateContext::new(sess,
llmod_id,
tcx,
emap2,
maps,
analysis.ty_cx,
analysis.exp_map2,
analysis.maps,
symbol_hasher,
link_meta,
reachable_map);
analysis.reachable);
{
let _icx = push_ctxt("data");
@ -3056,5 +3052,9 @@ pub fn trans_crate(sess: session::Session,
let link_meta = ccx.link_meta;
let llmod = ccx.llmod;
return (llcx, llmod, link_meta);
return CrateTranslation {
context: llcx,
module: llmod,
link: link_meta
};
}

View File

@ -223,13 +223,15 @@ fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str],
debug!("testing with ^^^^^^ %?", (||{ println(test) })());
let dinput = driver::str_input(test.to_managed());
let cfg = driver::build_configuration(sess, binary, &dinput);
let outputs = driver::build_output_filenames(&dinput, &None, &None, [], sess);
let (crate, tcx) = driver::compile_upto(sess, cfg.clone(), &dinput,
driver::cu_typeck, Some(outputs));
let crate = driver::phase_1_parse_input(sess, cfg.clone(), &dinput);
let expanded_crate = driver::phase_2_configure_and_expand(sess, cfg, crate);
let analysis = driver::phase_3_run_analysis_passes(sess, expanded_crate);
// Once we're typechecked, record the types of all local variables defined
// in this input
do find_main(crate.expect("crate after cu_typeck"), sess) |blk| {
program.register_new_vars(blk, tcx.expect("tcx after cu_typeck"));
do find_main(crate, sess) |blk| {
program.register_new_vars(blk, analysis.ty_cx);
}
//
@ -242,8 +244,12 @@ fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str],
let cfg = driver::build_configuration(sess, binary, &input);
let outputs = driver::build_output_filenames(&input, &None, &None, [], sess);
let sess = driver::build_session(options, diagnostic::emit);
driver::compile_upto(sess, cfg, &input, driver::cu_everything,
Some(outputs));
let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
let expanded_crate = driver::phase_2_configure_and_expand(sess, cfg, crate);
let analysis = driver::phase_3_run_analysis_passes(sess, expanded_crate);
let trans = driver::phase_4_translate_to_llvm(sess, expanded_crate, &analysis, outputs);
driver::phase_5_run_llvm_passes(sess, &trans, outputs);
//
// Stage 4: Inform the program that computation is done so it can update all
@ -265,10 +271,7 @@ fn parse_input(sess: session::Session, binary: @str,
let code = fmt!("fn main() {\n %s \n}", input);
let input = driver::str_input(code.to_managed());
let cfg = driver::build_configuration(sess, binary, &input);
let outputs = driver::build_output_filenames(&input, &None, &None, [], sess);
let (crate, _) = driver::compile_upto(sess, cfg, &input,
driver::cu_parse, Some(outputs));
crate.expect("parsing should return a crate")
driver::phase_1_parse_input(sess, cfg.clone(), &input)
}
fn find_main(crate: @ast::Crate, sess: session::Session,
@ -334,9 +337,12 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
None => { },
}
if (should_compile) {
printfln!("compiling %s...", src_filename);
driver::compile_upto(sess, cfg, &input, driver::cu_everything,
Some(outputs));
println(fmt!("compiling %s...", src_filename));
let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
let expanded_crate = driver::phase_2_configure_and_expand(sess, cfg, crate);
let analysis = driver::phase_3_run_analysis_passes(sess, expanded_crate);
let trans = driver::phase_4_translate_to_llvm(sess, expanded_crate, &analysis, outputs);
driver::phase_5_run_llvm_passes(sess, &trans, outputs);
true
} else { false }
} {

View File

@ -109,7 +109,8 @@ fn parse<'a>(script: Path, workspace: &Path, id: &'a PkgId) -> PkgScript<'a> {
let input = driver::file_input(script);
let sess = driver::build_session(options, diagnostic::emit);
let cfg = driver::build_configuration(sess, binary, &input);
let (crate, _) = driver::compile_upto(sess, cfg.clone(), &input, driver::cu_parse, None);
let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
let crate = driver::phase_2_configure_and_expand(sess, cfg.clone(), crate);
let work_dir = build_pkg_id_in_workspace(id, workspace);
debug!("Returning package script with id %?", id);
@ -119,7 +120,7 @@ fn parse<'a>(script: Path, workspace: &Path, id: &'a PkgId) -> PkgScript<'a> {
input: input,
sess: sess,
cfg: cfg,
crate: crate.unwrap(),
crate: crate,
build_dir: work_dir
}
}
@ -142,14 +143,10 @@ fn run_custom(&self, sysroot: @Path) -> (~[~str], ExitCode) {
let root = r.pop().pop().pop().pop(); // :-\
debug!("Root is %s, calling compile_rest", root.to_str());
let exe = self.build_dir.push(~"pkg" + util::exe_suffix());
let binary = os::args()[0].to_managed();
util::compile_crate_from_input(&self.input,
&self.build_dir,
sess,
crate,
driver::build_configuration(sess,
binary, &self.input),
driver::cu_parse);
crate);
debug!("Running program: %s %s %s %s", exe.to_str(),
sysroot.to_str(), root.to_str(), "install");
// FIXME #7401 should support commands besides `install`

View File

@ -18,7 +18,6 @@
use syntax::{ast, attr, codemap, diagnostic, fold};
use syntax::attr::AttrMetaMethods;
use rustc::back::link::output_type_exe;
use rustc::driver::driver::compile_upto;
use rustc::driver::session::{lib_crate, bin_crate};
use context::Ctx;
use package_id::PkgId;
@ -220,12 +219,8 @@ pub fn compile_input(ctxt: &Ctx,
// Infer dependencies that rustpkg needs to build, by scanning for
// `extern mod` directives.
let cfg = driver::build_configuration(sess, binary, &input);
let (crate_opt, _) = driver::compile_upto(sess, cfg.clone(), &input, driver::cu_expand, None);
let mut crate = match crate_opt {
Some(c) => c,
None => fail!("compile_input expected...")
};
let mut crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
crate = driver::phase_2_configure_and_expand(sess, cfg, crate);
// Not really right. Should search other workspaces too, and the installed
// database (which doesn't exist yet)
@ -257,7 +252,7 @@ pub fn compile_input(ctxt: &Ctx,
debug!("calling compile_crate_from_input, out_dir = %s,
building_library = %?", out_dir.to_str(), sess.building_library);
compile_crate_from_input(&input, out_dir, sess, crate, cfg.clone(), driver::cu_expand);
compile_crate_from_input(&input, out_dir, sess, crate);
true
}
@ -269,9 +264,7 @@ pub fn compile_input(ctxt: &Ctx,
pub fn compile_crate_from_input(input: &driver::input,
build_dir: &Path,
sess: session::Session,
crate: @ast::Crate,
cfg: ast::CrateConfig,
compile_from: driver::compile_phase) {
crate: @ast::Crate) {
debug!("Calling build_output_filenames with %s, building library? %?",
build_dir.to_str(), sess.building_library);
@ -284,15 +277,13 @@ pub fn compile_crate_from_input(input: &driver::input,
for sess.opts.addl_lib_search_paths.iter().advance |lib| {
debug!("an additional library: %s", lib.to_str());
}
driver::compile_rest(sess,
cfg,
compile_upto {
from: compile_from,
to: driver::cu_everything
},
Some(outputs),
Some(crate));
let analysis = driver::phase_3_run_analysis_passes(sess, crate);
let translation = driver::phase_4_translate_to_llvm(sess, crate,
&analysis,
outputs);
driver::phase_5_run_llvm_passes(sess, &translation, outputs);
if driver::stop_after_phase_5(sess) { return; }
driver::phase_6_link_output(sess, &translation, outputs);
}
#[cfg(windows)]