提交 74c92c55 编写于 作者: B bjorn3

Allow runtime switching between trans backends

上级 5965b790
...@@ -2010,7 +2010,6 @@ dependencies = [ ...@@ -2010,7 +2010,6 @@ dependencies = [
"rustc_const_math 0.0.0", "rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0", "rustc_data_structures 0.0.0",
"rustc_errors 0.0.0", "rustc_errors 0.0.0",
"rustc_trans_utils 0.0.0",
"serialize 0.0.0", "serialize 0.0.0",
"syntax 0.0.0", "syntax 0.0.0",
"syntax_pos 0.0.0", "syntax_pos 0.0.0",
...@@ -2133,6 +2132,8 @@ dependencies = [ ...@@ -2133,6 +2132,8 @@ dependencies = [
"rustc 0.0.0", "rustc 0.0.0",
"rustc_back 0.0.0", "rustc_back 0.0.0",
"rustc_data_structures 0.0.0", "rustc_data_structures 0.0.0",
"rustc_incremental 0.0.0",
"rustc_mir 0.0.0",
"syntax 0.0.0", "syntax 0.0.0",
"syntax_pos 0.0.0", "syntax_pos 0.0.0",
] ]
......
...@@ -1045,6 +1045,8 @@ fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) -> ...@@ -1045,6 +1045,8 @@ fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) ->
options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
build_debugging_options, "Z", "debugging", build_debugging_options, "Z", "debugging",
DB_OPTIONS, db_type_desc, dbsetters, DB_OPTIONS, db_type_desc, dbsetters,
codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
"the backend to use"),
verbose: bool = (false, parse_bool, [UNTRACKED], verbose: bool = (false, parse_bool, [UNTRACKED],
"in general, enable more debug printouts"), "in general, enable more debug printouts"),
span_free_formats: bool = (false, parse_bool, [UNTRACKED], span_free_formats: bool = (false, parse_bool, [UNTRACKED],
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
use rustc_resolve::{MakeGlobMap, Resolver}; use rustc_resolve::{MakeGlobMap, Resolver};
use rustc_metadata::creader::CrateLoader; use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::{self, CStore}; use rustc_metadata::cstore::{self, CStore};
use rustc_trans as trans;
use rustc_trans_utils::trans_crate::TransCrate; use rustc_trans_utils::trans_crate::TransCrate;
use rustc_typeck as typeck; use rustc_typeck as typeck;
use rustc_privacy; use rustc_privacy;
...@@ -40,7 +39,6 @@ ...@@ -40,7 +39,6 @@
use rustc_passes::{self, ast_validation, loops, consts, static_recursion, hir_stats}; use rustc_passes::{self, ast_validation, loops, consts, static_recursion, hir_stats};
use rustc_const_eval::{self, check_match}; use rustc_const_eval::{self, check_match};
use super::Compilation; use super::Compilation;
use ::DefaultTransCrate;
use serialize::json; use serialize::json;
...@@ -68,7 +66,8 @@ ...@@ -68,7 +66,8 @@
use profile; use profile;
pub fn compile_input(sess: &Session, pub fn compile_input(trans: Box<TransCrate>,
sess: &Session,
cstore: &CStore, cstore: &CStore,
input_path: &Option<PathBuf>, input_path: &Option<PathBuf>,
input: &Input, input: &Input,
...@@ -76,8 +75,6 @@ pub fn compile_input(sess: &Session, ...@@ -76,8 +75,6 @@ pub fn compile_input(sess: &Session,
output: &Option<PathBuf>, output: &Option<PathBuf>,
addl_plugins: Option<Vec<String>>, addl_plugins: Option<Vec<String>>,
control: &CompileController) -> CompileResult { control: &CompileController) -> CompileResult {
use rustc::session::config::CrateType;
macro_rules! controller_entry_point { macro_rules! controller_entry_point {
($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{ ($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
let state = &mut $make_state; let state = &mut $make_state;
...@@ -94,22 +91,6 @@ pub fn compile_input(sess: &Session, ...@@ -94,22 +91,6 @@ pub fn compile_input(sess: &Session,
}} }}
} }
if cfg!(not(feature="llvm")) {
for cty in sess.opts.crate_types.iter() {
match *cty {
CrateType::CrateTypeRlib | CrateType::CrateTypeDylib |
CrateType::CrateTypeExecutable => {},
_ => {
sess.parse_sess.span_diagnostic.warn(
&format!("LLVM unsupported, so output type {} is not supported", cty)
);
},
}
}
sess.abort_if_errors();
}
if sess.profile_queries() { if sess.profile_queries() {
profile::begin(); profile::begin();
} }
...@@ -117,7 +98,7 @@ pub fn compile_input(sess: &Session, ...@@ -117,7 +98,7 @@ pub fn compile_input(sess: &Session,
// We need nested scopes here, because the intermediate results can keep // 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 // large chunks of memory alive and we want to free them as soon as
// possible to keep the peak memory usage low // possible to keep the peak memory usage low
let (outputs, trans, dep_graph) = { let (outputs, ongoing_trans, dep_graph) = {
let krate = match phase_1_parse_input(control, sess, input) { let krate = match phase_1_parse_input(control, sess, input) {
Ok(krate) => krate, Ok(krate) => krate,
Err(mut parse_error) => { Err(mut parse_error) => {
...@@ -217,7 +198,8 @@ pub fn compile_input(sess: &Session, ...@@ -217,7 +198,8 @@ pub fn compile_input(sess: &Session,
None None
}; };
phase_3_run_analysis_passes(control, phase_3_run_analysis_passes(&*trans,
control,
sess, sess,
cstore, cstore,
hir_map, hir_map,
...@@ -254,7 +236,7 @@ pub fn compile_input(sess: &Session, ...@@ -254,7 +236,7 @@ pub fn compile_input(sess: &Session,
tcx.print_debug_stats(); tcx.print_debug_stats();
} }
let trans = phase_4_translate_to_llvm::<DefaultTransCrate>(tcx, rx); let ongoing_trans = phase_4_translate_to_llvm(&*trans, tcx, rx);
if log_enabled!(::log::Level::Info) { if log_enabled!(::log::Level::Info) {
println!("Post-trans"); println!("Post-trans");
...@@ -268,7 +250,7 @@ pub fn compile_input(sess: &Session, ...@@ -268,7 +250,7 @@ pub fn compile_input(sess: &Session,
} }
} }
Ok((outputs.clone(), trans, tcx.dep_graph.clone())) Ok((outputs.clone(), ongoing_trans, tcx.dep_graph.clone()))
})?? })??
}; };
...@@ -276,25 +258,7 @@ pub fn compile_input(sess: &Session, ...@@ -276,25 +258,7 @@ pub fn compile_input(sess: &Session,
sess.code_stats.borrow().print_type_sizes(); sess.code_stats.borrow().print_type_sizes();
} }
let (phase5_result, trans) = trans.join_trans_and_link(ongoing_trans, sess, &dep_graph, &outputs)?;
phase_5_run_llvm_passes::<DefaultTransCrate>(sess, &dep_graph, trans);
controller_entry_point!(after_llvm,
sess,
CompileState::state_after_llvm(input, sess, outdir, output, &trans),
phase5_result);
phase5_result?;
// Run the linker on any artifacts that resulted from the LLVM run.
// This should produce either a finished executable or library.
time(sess.time_passes(), "linking", || {
DefaultTransCrate::link_binary(sess, &trans, &outputs)
});
// Now that we won't touch anything in the incremental compilation directory
// any more, we can finalize it (which involves renaming it)
#[cfg(feature="llvm")]
rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
if sess.opts.debugging_opts.perf_stats { if sess.opts.debugging_opts.perf_stats {
sess.print_perf_stats(); sess.print_perf_stats();
...@@ -340,7 +304,6 @@ pub struct CompileController<'a> { ...@@ -340,7 +304,6 @@ pub struct CompileController<'a> {
pub after_expand: PhaseController<'a>, pub after_expand: PhaseController<'a>,
pub after_hir_lowering: PhaseController<'a>, pub after_hir_lowering: PhaseController<'a>,
pub after_analysis: PhaseController<'a>, pub after_analysis: PhaseController<'a>,
pub after_llvm: PhaseController<'a>,
pub compilation_done: PhaseController<'a>, pub compilation_done: PhaseController<'a>,
// FIXME we probably want to group the below options together and offer a // FIXME we probably want to group the below options together and offer a
...@@ -366,7 +329,6 @@ pub fn basic() -> CompileController<'a> { ...@@ -366,7 +329,6 @@ pub fn basic() -> CompileController<'a> {
after_expand: PhaseController::basic(), after_expand: PhaseController::basic(),
after_hir_lowering: PhaseController::basic(), after_hir_lowering: PhaseController::basic(),
after_analysis: PhaseController::basic(), after_analysis: PhaseController::basic(),
after_llvm: PhaseController::basic(),
compilation_done: PhaseController::basic(), compilation_done: PhaseController::basic(),
make_glob_map: MakeGlobMap::No, make_glob_map: MakeGlobMap::No,
keep_ast: false, keep_ast: false,
...@@ -415,7 +377,6 @@ pub struct CompileState<'a, 'tcx: 'a> { ...@@ -415,7 +377,6 @@ pub struct CompileState<'a, 'tcx: 'a> {
pub resolutions: Option<&'a Resolutions>, pub resolutions: Option<&'a Resolutions>,
pub analysis: Option<&'a ty::CrateAnalysis>, pub analysis: Option<&'a ty::CrateAnalysis>,
pub tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>, pub tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
pub trans: Option<&'a trans::CrateTranslation>,
} }
impl<'a, 'tcx> CompileState<'a, 'tcx> { impl<'a, 'tcx> CompileState<'a, 'tcx> {
...@@ -440,7 +401,6 @@ fn empty(input: &'a Input, ...@@ -440,7 +401,6 @@ fn empty(input: &'a Input,
resolutions: None, resolutions: None,
analysis: None, analysis: None,
tcx: None, tcx: None,
trans: None,
} }
} }
...@@ -528,19 +488,6 @@ fn state_after_analysis(input: &'a Input, ...@@ -528,19 +488,6 @@ fn state_after_analysis(input: &'a Input,
} }
} }
fn state_after_llvm(input: &'a Input,
session: &'tcx Session,
out_dir: &'a Option<PathBuf>,
out_file: &'a Option<PathBuf>,
trans: &'a trans::CrateTranslation)
-> Self {
CompileState {
trans: Some(trans),
out_file: out_file.as_ref().map(|s| &**s),
..CompileState::empty(input, session, out_dir)
}
}
fn state_when_compilation_done(input: &'a Input, fn state_when_compilation_done(input: &'a Input,
session: &'tcx Session, session: &'tcx Session,
out_dir: &'a Option<PathBuf>, out_dir: &'a Option<PathBuf>,
...@@ -933,7 +880,6 @@ pub fn default_provide(providers: &mut ty::maps::Providers) { ...@@ -933,7 +880,6 @@ pub fn default_provide(providers: &mut ty::maps::Providers) {
reachable::provide(providers); reachable::provide(providers);
resolve_lifetime::provide(providers); resolve_lifetime::provide(providers);
rustc_privacy::provide(providers); rustc_privacy::provide(providers);
DefaultTransCrate::provide(providers);
typeck::provide(providers); typeck::provide(providers);
ty::provide(providers); ty::provide(providers);
traits::provide(providers); traits::provide(providers);
...@@ -947,13 +893,13 @@ pub fn default_provide(providers: &mut ty::maps::Providers) { ...@@ -947,13 +893,13 @@ pub fn default_provide(providers: &mut ty::maps::Providers) {
pub fn default_provide_extern(providers: &mut ty::maps::Providers) { pub fn default_provide_extern(providers: &mut ty::maps::Providers) {
cstore::provide_extern(providers); cstore::provide_extern(providers);
DefaultTransCrate::provide_extern(providers);
} }
/// Run the resolution, typechecking, region checking and other /// Run the resolution, typechecking, region checking and other
/// miscellaneous analysis passes on the crate. Return various /// miscellaneous analysis passes on the crate. Return various
/// structures carrying the results of the analysis. /// structures carrying the results of the analysis.
pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController, pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate,
control: &CompileController,
sess: &'tcx Session, sess: &'tcx Session,
cstore: &'tcx CrateStore, cstore: &'tcx CrateStore,
hir_map: hir_map::Map<'tcx>, hir_map: hir_map::Map<'tcx>,
...@@ -1006,10 +952,12 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController, ...@@ -1006,10 +952,12 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController,
let mut local_providers = ty::maps::Providers::default(); let mut local_providers = ty::maps::Providers::default();
default_provide(&mut local_providers); default_provide(&mut local_providers);
trans.provide(&mut local_providers);
(control.provide)(&mut local_providers); (control.provide)(&mut local_providers);
let mut extern_providers = local_providers; let mut extern_providers = local_providers;
default_provide_extern(&mut extern_providers); default_provide_extern(&mut extern_providers);
trans.provide_extern(&mut extern_providers);
(control.provide_extern)(&mut extern_providers); (control.provide_extern)(&mut extern_providers);
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
...@@ -1101,9 +1049,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController, ...@@ -1101,9 +1049,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController,
/// Run the translation phase to LLVM, after which the AST and analysis can /// Run the translation phase to LLVM, after which the AST and analysis can
/// be discarded. /// be discarded.
pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn phase_4_translate_to_llvm<'a, 'tcx>(trans: &TransCrate,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
rx: mpsc::Receiver<Box<Any + Send>>) rx: mpsc::Receiver<Box<Any + Send>>)
-> <Trans as TransCrate>::OngoingCrateTranslation { -> Box<Any> {
let time_passes = tcx.sess.time_passes(); let time_passes = tcx.sess.time_passes();
time(time_passes, time(time_passes,
...@@ -1112,7 +1061,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 't ...@@ -1112,7 +1061,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 't
let translation = let translation =
time(time_passes, "translation", move || { time(time_passes, "translation", move || {
Trans::trans_crate(tcx, rx) trans.trans_crate(tcx, rx)
}); });
if tcx.sess.profile_queries() { if tcx.sess.profile_queries() {
profile::dump("profile_queries".to_string()) profile::dump("profile_queries".to_string())
...@@ -1121,25 +1070,6 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 't ...@@ -1121,25 +1070,6 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 't
translation translation
} }
/// Run LLVM itself, producing a bitcode file, assembly file or object file
/// as a side effect.
pub fn phase_5_run_llvm_passes<Trans: TransCrate>(sess: &Session,
dep_graph: &DepGraph,
trans: <Trans as TransCrate>::OngoingCrateTranslation)
-> (CompileResult, <Trans as TransCrate>::TranslatedCrate) {
let trans = Trans::join_trans(trans, sess, dep_graph);
if sess.opts.debugging_opts.incremental_info {
Trans::dump_incremental_data(&trans);
}
time(sess.time_passes(),
"serialize work products",
move || rustc_incremental::save_work_products(sess, dep_graph));
(sess.compile_status(), trans)
}
fn escape_dep_filename(filename: &FileName) -> String { fn escape_dep_filename(filename: &FileName) -> String {
// Apparently clang and gcc *only* escape spaces: // Apparently clang and gcc *only* escape spaces:
// http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4 // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
extern crate rustc_resolve; extern crate rustc_resolve;
extern crate rustc_save_analysis; extern crate rustc_save_analysis;
#[cfg(feature="llvm")] #[cfg(feature="llvm")]
extern crate rustc_trans; pub extern crate rustc_trans;
extern crate rustc_trans_utils; extern crate rustc_trans_utils;
extern crate rustc_typeck; extern crate rustc_typeck;
extern crate serialize; extern crate serialize;
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
use rustc_save_analysis::DumpHandler; use rustc_save_analysis::DumpHandler;
use rustc::session::{self, config, Session, build_session, CompileResult}; use rustc::session::{self, config, Session, build_session, CompileResult};
use rustc::session::CompileIncomplete; use rustc::session::CompileIncomplete;
use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType}; use rustc::session::config::{Input, PrintRequest, ErrorOutputType};
use rustc::session::config::nightly_options; use rustc::session::config::nightly_options;
use rustc::session::{early_error, early_warn}; use rustc::session::{early_error, early_warn};
use rustc::lint::Lint; use rustc::lint::Lint;
...@@ -106,9 +106,32 @@ ...@@ -106,9 +106,32 @@
pub mod profile; pub mod profile;
pub mod driver; pub mod driver;
pub mod pretty; pub mod pretty;
pub mod target_features;
mod derive_registrar; mod derive_registrar;
pub mod target_features {
use syntax::ast;
use syntax::symbol::Symbol;
use rustc::session::Session;
use rustc_trans_utils::trans_crate::TransCrate;
/// Add `target_feature = "..."` cfgs for a variety of platform
/// specific features (SSE, NEON etc.).
///
/// This is performed by checking whether a whitelisted set of
/// features is available on the target machine, by querying LLVM.
pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session, trans: &TransCrate) {
let tf = Symbol::intern("target_feature");
for feat in trans.target_features(sess) {
cfg.insert((tf, Some(feat)));
}
if sess.crt_static_feature() {
cfg.insert((tf, Some(Symbol::intern("crt-static"))));
}
}
}
const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\ const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
md#bug-reports"; md#bug-reports";
...@@ -159,25 +182,22 @@ pub fn run<F>(run_compiler: F) -> isize ...@@ -159,25 +182,22 @@ pub fn run<F>(run_compiler: F) -> isize
pub use rustc_trans::LlvmTransCrate as DefaultTransCrate; pub use rustc_trans::LlvmTransCrate as DefaultTransCrate;
#[cfg(not(feature="llvm"))] #[cfg(not(feature="llvm"))]
mod rustc_trans { pub mod rustc_trans {
use syntax_pos::symbol::Symbol;
use rustc::session::Session;
use rustc::session::config::PrintRequest;
pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as LlvmTransCrate; pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as LlvmTransCrate;
pub use rustc_trans_utils::trans_crate::TranslatedCrate as CrateTranslation;
pub fn init(_sess: &Session) {}
pub fn print_version() {} pub fn print_version() {}
pub fn print_passes() {} pub fn print_passes() {}
pub fn print(_req: PrintRequest, _sess: &Session) {} }
pub fn target_features(_sess: &Session) -> Vec<Symbol> { vec![] }
pub mod back { pub fn get_trans(sess: &Session) -> Box<TransCrate> {
pub mod write { let trans_name = sess.opts.debugging_opts.codegen_backend.clone();
pub const RELOC_MODEL_ARGS: [(&'static str, ()); 0] = []; match trans_name.as_ref().map(|s|&**s) {
pub const CODE_GEN_MODEL_ARGS: [(&'static str, ()); 0] = []; None => DefaultTransCrate::new(&sess),
pub const TLS_MODEL_ARGS: [(&'static str, ()); 0] = []; Some("llvm") => rustc_trans::LlvmTransCrate::new(&sess),
Some("metadata_only") => {
rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new(&sess)
} }
Some(trans_name) => sess.fatal(&format!("Invalid trans {}", trans_name)),
} }
} }
...@@ -222,30 +242,36 @@ pub fn run_compiler<'a>(args: &[String], ...@@ -222,30 +242,36 @@ pub fn run_compiler<'a>(args: &[String],
}, },
}; };
let cstore = CStore::new(DefaultTransCrate::metadata_loader());
let loader = file_loader.unwrap_or(box RealFileLoader); let loader = file_loader.unwrap_or(box RealFileLoader);
let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping())); let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
let mut sess = session::build_session_with_codemap( let mut sess = session::build_session_with_codemap(
sopts, input_file_path.clone(), descriptions, codemap, emitter_dest, sopts, input_file_path.clone(), descriptions, codemap, emitter_dest,
); );
rustc_trans::init(&sess);
let trans = get_trans(&sess);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess, cfg); let mut cfg = config::build_configuration(&sess, cfg);
target_features::add_configuration(&mut cfg, &sess); target_features::add_configuration(&mut cfg, &sess, &*trans);
sess.parse_sess.config = cfg; sess.parse_sess.config = cfg;
do_or_return!(callbacks.late_callback(&matches, let plugins = sess.opts.debugging_opts.extra_plugins.clone();
let cstore = CStore::new(trans.metadata_loader());
do_or_return!(callbacks.late_callback(&*trans,
&matches,
&sess, &sess,
&cstore, &cstore,
&input, &input,
&odir, &odir,
&ofile), Some(sess)); &ofile), Some(sess));
let plugins = sess.opts.debugging_opts.extra_plugins.clone();
let control = callbacks.build_controller(&sess, &matches); let control = callbacks.build_controller(&sess, &matches);
(driver::compile_input(&sess,
(driver::compile_input(trans,
&sess,
&cstore, &cstore,
&input_file_path, &input_file_path,
&input, &input,
...@@ -338,6 +364,7 @@ fn early_callback(&mut self, ...@@ -338,6 +364,7 @@ fn early_callback(&mut self,
// be called just before actual compilation starts (and before build_controller // be called just before actual compilation starts (and before build_controller
// is called), after all arguments etc. have been completely handled. // is called), after all arguments etc. have been completely handled.
fn late_callback(&mut self, fn late_callback(&mut self,
_: &TransCrate,
_: &getopts::Matches, _: &getopts::Matches,
_: &Session, _: &Session,
_: &CrateStore, _: &CrateStore,
...@@ -517,13 +544,18 @@ fn no_input(&mut self, ...@@ -517,13 +544,18 @@ fn no_input(&mut self,
let mut sess = build_session(sopts.clone(), let mut sess = build_session(sopts.clone(),
None, None,
descriptions.clone()); descriptions.clone());
rustc_trans::init(&sess);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess, cfg.clone()); let mut cfg = config::build_configuration(&sess, cfg.clone());
target_features::add_configuration(&mut cfg, &sess); let trans = get_trans(&sess);
target_features::add_configuration(&mut cfg, &sess, &*trans);
sess.parse_sess.config = cfg; sess.parse_sess.config = cfg;
let should_stop = let should_stop = RustcDefaultCalls::print_crate_info(
RustcDefaultCalls::print_crate_info(&sess, None, odir, ofile); &*trans,
&sess,
None,
odir,
ofile
);
if should_stop == Compilation::Stop { if should_stop == Compilation::Stop {
return None; return None;
...@@ -536,6 +568,7 @@ fn no_input(&mut self, ...@@ -536,6 +568,7 @@ fn no_input(&mut self,
} }
fn late_callback(&mut self, fn late_callback(&mut self,
trans: &TransCrate,
matches: &getopts::Matches, matches: &getopts::Matches,
sess: &Session, sess: &Session,
cstore: &CrateStore, cstore: &CrateStore,
...@@ -543,7 +576,7 @@ fn late_callback(&mut self, ...@@ -543,7 +576,7 @@ fn late_callback(&mut self,
odir: &Option<PathBuf>, odir: &Option<PathBuf>,
ofile: &Option<PathBuf>) ofile: &Option<PathBuf>)
-> Compilation { -> Compilation {
RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile) RustcDefaultCalls::print_crate_info(trans, sess, Some(input), odir, ofile)
.and_then(|| RustcDefaultCalls::list_metadata(sess, cstore, matches, input)) .and_then(|| RustcDefaultCalls::list_metadata(sess, cstore, matches, input))
} }
...@@ -607,11 +640,6 @@ fn build_controller(&mut self, ...@@ -607,11 +640,6 @@ fn build_controller(&mut self,
control.after_hir_lowering.stop = Compilation::Stop; control.after_hir_lowering.stop = Compilation::Stop;
} }
if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
i == OutputType::Metadata) {
control.after_llvm.stop = Compilation::Stop;
}
if save_analysis(sess) { if save_analysis(sess) {
enable_save_analysis(&mut control); enable_save_analysis(&mut control);
} }
...@@ -681,11 +709,13 @@ pub fn list_metadata(sess: &Session, ...@@ -681,11 +709,13 @@ pub fn list_metadata(sess: &Session,
} }
fn print_crate_info(sess: &Session, fn print_crate_info(trans: &TransCrate,
sess: &Session,
input: Option<&Input>, input: Option<&Input>,
odir: &Option<PathBuf>, odir: &Option<PathBuf>,
ofile: &Option<PathBuf>) ofile: &Option<PathBuf>)
-> Compilation { -> Compilation {
use rustc::session::config::PrintRequest::*;
// PrintRequest::NativeStaticLibs is special - printed during linking // PrintRequest::NativeStaticLibs is special - printed during linking
// (empty iterator returns true) // (empty iterator returns true)
if sess.opts.prints.iter().all(|&p| p==PrintRequest::NativeStaticLibs) { if sess.opts.prints.iter().all(|&p| p==PrintRequest::NativeStaticLibs) {
...@@ -707,15 +737,14 @@ fn print_crate_info(sess: &Session, ...@@ -707,15 +737,14 @@ fn print_crate_info(sess: &Session,
}; };
for req in &sess.opts.prints { for req in &sess.opts.prints {
match *req { match *req {
PrintRequest::TargetList => { TargetList => {
let mut targets = rustc_back::target::get_targets().collect::<Vec<String>>(); let mut targets = rustc_back::target::get_targets().collect::<Vec<String>>();
targets.sort(); targets.sort();
println!("{}", targets.join("\n")); println!("{}", targets.join("\n"));
}, },
PrintRequest::Sysroot => println!("{}", sess.sysroot().display()), Sysroot => println!("{}", sess.sysroot().display()),
PrintRequest::TargetSpec => println!("{}", sess.target.target.to_json().pretty()), TargetSpec => println!("{}", sess.target.target.to_json().pretty()),
PrintRequest::FileNames | FileNames | CrateName => {
PrintRequest::CrateName => {
let input = match input { let input = match input {
Some(input) => input, Some(input) => input,
None => early_error(ErrorOutputType::default(), "no input file provided"), None => early_error(ErrorOutputType::default(), "no input file provided"),
...@@ -741,7 +770,7 @@ fn print_crate_info(sess: &Session, ...@@ -741,7 +770,7 @@ fn print_crate_info(sess: &Session,
.to_string_lossy()); .to_string_lossy());
} }
} }
PrintRequest::Cfg => { Cfg => {
let allow_unstable_cfg = UnstableFeatures::from_environment() let allow_unstable_cfg = UnstableFeatures::from_environment()
.is_nightly_build(); .is_nightly_build();
...@@ -781,29 +810,8 @@ fn print_crate_info(sess: &Session, ...@@ -781,29 +810,8 @@ fn print_crate_info(sess: &Session,
println!("{}", cfg); println!("{}", cfg);
} }
} }
PrintRequest::RelocationModels => { RelocationModels | CodeModels | TlsModels | TargetCPUs | TargetFeatures => {
println!("Available relocation models:"); trans.print(*req, sess);
for &(name, _) in rustc_trans::back::write::RELOC_MODEL_ARGS.iter() {
println!(" {}", name);
}
println!("");
}
PrintRequest::CodeModels => {
println!("Available code models:");
for &(name, _) in rustc_trans::back::write::CODE_GEN_MODEL_ARGS.iter(){
println!(" {}", name);
}
println!("");
}
PrintRequest::TlsModels => {
println!("Available TLS models:");
for &(name, _) in rustc_trans::back::write::TLS_MODEL_ARGS.iter(){
println!(" {}", name);
}
println!("");
}
PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => {
rustc_trans::print(*req, sess);
} }
// Any output here interferes with Cargo's parsing of other printed output // Any output here interferes with Cargo's parsing of other printed output
PrintRequest::NativeStaticLibs => {} PrintRequest::NativeStaticLibs => {}
...@@ -1281,6 +1289,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry { ...@@ -1281,6 +1289,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
#[cfg(feature="llvm")] #[cfg(feature="llvm")]
all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS);
all_errors.extend_from_slice(&rustc_trans_utils::DIAGNOSTICS);
all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS);
all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS);
all_errors.extend_from_slice(&rustc_passes::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_passes::DIAGNOSTICS);
......
...@@ -228,7 +228,8 @@ fn call_with_pp_support_hir<'tcx, A, F>(&self, ...@@ -228,7 +228,8 @@ fn call_with_pp_support_hir<'tcx, A, F>(&self,
} }
PpmTyped => { PpmTyped => {
let control = &driver::CompileController::basic(); let control = &driver::CompileController::basic();
abort_on_err(driver::phase_3_run_analysis_passes(control, abort_on_err(driver::phase_3_run_analysis_passes(&*::DefaultTransCrate::new(&sess),
control,
sess, sess,
cstore, cstore,
hir_map.clone(), hir_map.clone(),
...@@ -1080,7 +1081,8 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, ...@@ -1080,7 +1081,8 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
let mut out = Vec::new(); let mut out = Vec::new();
let control = &driver::CompileController::basic(); let control = &driver::CompileController::basic();
abort_on_err(driver::phase_3_run_analysis_passes(control, abort_on_err(driver::phase_3_run_analysis_passes(&*::DefaultTransCrate::new(&sess),
control,
sess, sess,
cstore, cstore,
hir_map.clone(), hir_map.clone(),
......
...@@ -104,7 +104,7 @@ fn test_env<F>(source_string: &str, ...@@ -104,7 +104,7 @@ fn test_env<F>(source_string: &str,
options.unstable_features = UnstableFeatures::Allow; options.unstable_features = UnstableFeatures::Allow;
let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter); let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter);
let cstore = Rc::new(CStore::new(::DefaultTransCrate::metadata_loader())); let cstore = Rc::new(CStore::new(::DefaultTransCrate::new().metadata_loader()));
let sess = session::build_session_(options, let sess = session::build_session_(options,
None, None,
diagnostic_handler, diagnostic_handler,
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
enum Disposition { Reused, Translated } enum Disposition { Reused, Translated }
pub(crate) fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { pub fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
tcx.dep_graph.with_ignore(|| { tcx.dep_graph.with_ignore(|| {
if tcx.sess.opts.incremental.is_none() { if tcx.sess.opts.incremental.is_none() {
return; return;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
extern crate syntax_pos; extern crate syntax_pos;
mod assert_dep_graph; mod assert_dep_graph;
pub mod assert_module_sources;
mod persist; mod persist;
pub use assert_dep_graph::assert_dep_graph; pub use assert_dep_graph::assert_dep_graph;
......
...@@ -24,4 +24,3 @@ syntax = { path = "../libsyntax" } ...@@ -24,4 +24,3 @@ syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" } syntax_pos = { path = "../libsyntax_pos" }
byteorder = { version = "1.1", features = ["i128"] } byteorder = { version = "1.1", features = ["i128"] }
rustc_apfloat = { path = "../librustc_apfloat" } rustc_apfloat = { path = "../librustc_apfloat" }
rustc_trans_utils = { path = "../librustc_trans_utils" }
...@@ -57,7 +57,6 @@ ...@@ -57,7 +57,6 @@
extern crate log_settings; extern crate log_settings;
extern crate rustc_apfloat; extern crate rustc_apfloat;
extern crate byteorder; extern crate byteorder;
extern crate rustc_trans_utils;
mod diagnostics; mod diagnostics;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
use std::iter; use std::iter;
use rustc::mir::mono::Linkage; use rustc::mir::mono::Linkage;
use syntax_pos::symbol::Symbol; use syntax_pos::symbol::Symbol;
use syntax::codemap::Span;
pub use rustc::mir::mono::MonoItem; pub use rustc::mir::mono::MonoItem;
pub fn linkage_by_name(name: &str) -> Option<Linkage> { pub fn linkage_by_name(name: &str) -> Option<Linkage> {
...@@ -244,6 +245,18 @@ fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ...@@ -244,6 +245,18 @@ fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
result result
} }
} }
fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
match *self.as_mono_item() {
MonoItem::Fn(Instance { def, .. }) => {
tcx.hir.as_local_node_id(def.def_id())
}
MonoItem::Static(node_id) |
MonoItem::GlobalAsm(node_id) => {
Some(node_id)
}
}.map(|node_id| tcx.hir.span(node_id))
}
} }
impl<'a, 'tcx> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { impl<'a, 'tcx> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
......
...@@ -22,6 +22,54 @@ ...@@ -22,6 +22,54 @@
pub mod item; pub mod item;
pub mod partitioning; pub mod partitioning;
#[inline(never)] // give this a place in the profiler
pub fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I)
where I: Iterator<Item=&'a MonoItem<'tcx>>
{
let mut symbols: Vec<_> = trans_items.map(|trans_item| {
(trans_item, trans_item.symbol_name(tcx))
}).collect();
(&mut symbols[..]).sort_by(|&(_, ref sym1), &(_, ref sym2)|{
sym1.cmp(sym2)
});
for pair in (&symbols[..]).windows(2) {
let sym1 = &pair[0].1;
let sym2 = &pair[1].1;
if *sym1 == *sym2 {
let trans_item1 = pair[0].0;
let trans_item2 = pair[1].0;
let span1 = trans_item1.local_span(tcx);
let span2 = trans_item2.local_span(tcx);
// Deterministically select one of the spans for error reporting
let span = match (span1, span2) {
(Some(span1), Some(span2)) => {
Some(if span1.lo().0 > span2.lo().0 {
span1
} else {
span2
})
}
(Some(span), None) |
(None, Some(span)) => Some(span),
_ => None
};
let error_message = format!("symbol `{}` is already defined", sym1);
if let Some(span) = span {
tcx.sess.span_fatal(span, &error_message)
} else {
tcx.sess.fatal(&error_message)
}
}
}
}
fn fn_once_adapter_instance<'a, 'tcx>( fn fn_once_adapter_instance<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
closure_did: DefId, closure_did: DefId,
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
use std::ffi::{OsStr, OsString}; use std::ffi::{OsStr, OsString};
use std::fmt; use std::fmt;
use std::io; use std::io;
use std::process::{self, Output, Child}; use std::process::{self, Output};
pub struct Command { pub struct Command {
program: OsString, program: OsString,
...@@ -81,10 +81,6 @@ pub fn output(&mut self) -> io::Result<Output> { ...@@ -81,10 +81,6 @@ pub fn output(&mut self) -> io::Result<Output> {
self.command().output() self.command().output()
} }
pub fn spawn(&mut self) -> io::Result<Child> {
self.command().spawn()
}
pub fn command(&self) -> process::Command { pub fn command(&self) -> process::Command {
let mut ret = process::Command::new(&self.program); let mut ret = process::Command::new(&self.program);
ret.args(&self.args); ret.args(&self.args);
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
use super::ModuleKind; use super::ModuleKind;
use abi; use abi;
use assert_module_sources;
use back::link; use back::link;
use back::symbol_export; use back::symbol_export;
use back::write::{self, OngoingCrateTranslation, create_target_machine}; use back::write::{self, OngoingCrateTranslation, create_target_machine};
...@@ -66,7 +65,7 @@ ...@@ -66,7 +65,7 @@
use mir; use mir;
use monomorphize::Instance; use monomorphize::Instance;
use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt}; use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
use symbol_names_test; use rustc_trans_utils::symbol_names_test;
use time_graph; use time_graph;
use trans_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames}; use trans_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames};
use type_::Type; use type_::Type;
...@@ -904,7 +903,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ...@@ -904,7 +903,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
total_trans_time); total_trans_time);
if tcx.sess.opts.incremental.is_some() { if tcx.sess.opts.incremental.is_some() {
assert_module_sources::assert_module_sources(tcx); ::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
} }
symbol_names_test::report_symbol_names(tcx); symbol_names_test::report_symbol_names(tcx);
...@@ -947,54 +946,6 @@ fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { ...@@ -947,54 +946,6 @@ fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|| rustc_incremental::save_dep_graph(tcx)); || rustc_incremental::save_dep_graph(tcx));
} }
#[inline(never)] // give this a place in the profiler
fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I)
where I: Iterator<Item=&'a MonoItem<'tcx>>
{
let mut symbols: Vec<_> = trans_items.map(|trans_item| {
(trans_item, trans_item.symbol_name(tcx))
}).collect();
(&mut symbols[..]).sort_by(|&(_, ref sym1), &(_, ref sym2)|{
sym1.cmp(sym2)
});
for pair in (&symbols[..]).windows(2) {
let sym1 = &pair[0].1;
let sym2 = &pair[1].1;
if *sym1 == *sym2 {
let trans_item1 = pair[0].0;
let trans_item2 = pair[1].0;
let span1 = trans_item1.local_span(tcx);
let span2 = trans_item2.local_span(tcx);
// Deterministically select one of the spans for error reporting
let span = match (span1, span2) {
(Some(span1), Some(span2)) => {
Some(if span1.lo().0 > span2.lo().0 {
span1
} else {
span2
})
}
(Some(span), None) |
(None, Some(span)) => Some(span),
_ => None
};
let error_message = format!("symbol `{}` is already defined", sym1);
if let Some(span) = span {
tcx.sess.span_fatal(span, &error_message)
} else {
tcx.sess.fatal(&error_message)
}
}
}
}
fn collect_and_partition_translation_items<'a, 'tcx>( fn collect_and_partition_translation_items<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
cnum: CrateNum, cnum: CrateNum,
...@@ -1034,7 +985,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>( ...@@ -1034,7 +985,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
collector::collect_crate_mono_items(tcx, collection_mode) collector::collect_crate_mono_items(tcx, collection_mode)
}); });
assert_symbols_are_distinct(tcx, items.iter()); ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
let strategy = if tcx.sess.opts.incremental.is_some() { let strategy = if tcx.sess.opts.incremental.is_some() {
PartitioningStrategy::PerModule PartitioningStrategy::PerModule
......
...@@ -47,27 +47,9 @@ fn main() { ...@@ -47,27 +47,9 @@ fn main() {
``` ```
"##, "##,
E0558: r##" }
The `export_name` attribute was malformed.
Erroneous code example:
```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
#[export_name] // error: export_name attribute has invalid format
pub fn something() {}
fn main() {}
```
The `export_name` attribute expects a string in order to determine the name of
the exported symbol. Example:
```
#[export_name = "some_function"] // ok!
pub fn something() {}
fn main() {}
```
"##,
register_diagnostics! {
E0558
} }
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#![feature(rustc_diagnostic_macros)] #![feature(rustc_diagnostic_macros)]
#![feature(slice_patterns)] #![feature(slice_patterns)]
#![feature(conservative_impl_trait)] #![feature(conservative_impl_trait)]
#![feature(optin_builtin_traits)]
use rustc::dep_graph::WorkProduct; use rustc::dep_graph::WorkProduct;
use syntax_pos::symbol::Symbol; use syntax_pos::symbol::Symbol;
...@@ -66,11 +67,9 @@ ...@@ -66,11 +67,9 @@
extern crate cc; // Used to locate MSVC extern crate cc; // Used to locate MSVC
extern crate tempdir; extern crate tempdir;
pub use base::trans_crate;
use back::bytecode::RLIB_BYTECODE_EXTENSION; use back::bytecode::RLIB_BYTECODE_EXTENSION;
pub use metadata::LlvmMetadataLoader; pub use llvm_util::{target_features, print_version, print_passes};
pub use llvm_util::{init, target_features, print_version, print_passes, print};
use std::any::Any; use std::any::Any;
use std::path::PathBuf; use std::path::PathBuf;
...@@ -81,16 +80,16 @@ ...@@ -81,16 +80,16 @@
use rustc::hir::def_id::CrateNum; use rustc::hir::def_id::CrateNum;
use rustc::middle::cstore::MetadataLoader; use rustc::middle::cstore::MetadataLoader;
use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource}; use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource};
use rustc::session::Session; use rustc::session::{Session, CompileIncomplete};
use rustc::session::config::{OutputFilenames, OutputType}; use rustc::session::config::{OutputFilenames, OutputType, PrintRequest};
use rustc::ty::{self, TyCtxt}; use rustc::ty::{self, TyCtxt};
use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::util::nodemap::{FxHashSet, FxHashMap};
use rustc_mir::monomorphize; use rustc_mir::monomorphize;
use rustc_trans_utils::trans_crate::TransCrate;
mod diagnostics; mod diagnostics;
pub mod back { pub(crate) mod back {
mod archive; mod archive;
pub mod bytecode; pub mod bytecode;
mod command; mod command;
...@@ -98,7 +97,7 @@ pub mod back { ...@@ -98,7 +97,7 @@ pub mod back {
pub mod link; pub mod link;
mod lto; mod lto;
pub(crate) mod symbol_export; pub(crate) mod symbol_export;
pub(crate) mod symbol_names; pub(crate) use rustc_trans_utils::symbol_names;
pub mod write; pub mod write;
mod rpath; mod rpath;
} }
...@@ -106,7 +105,6 @@ pub mod back { ...@@ -106,7 +105,6 @@ pub mod back {
mod abi; mod abi;
mod allocator; mod allocator;
mod asm; mod asm;
mod assert_module_sources;
mod attributes; mod attributes;
mod base; mod base;
mod builder; mod builder;
...@@ -139,7 +137,6 @@ pub mod back { ...@@ -139,7 +137,6 @@ pub mod back {
mod metadata; mod metadata;
mod meth; mod meth;
mod mir; mod mir;
mod symbol_names_test;
mod time_graph; mod time_graph;
mod trans_item; mod trans_item;
mod type_; mod type_;
...@@ -148,53 +145,108 @@ pub mod back { ...@@ -148,53 +145,108 @@ pub mod back {
pub struct LlvmTransCrate(()); pub struct LlvmTransCrate(());
impl !Send for LlvmTransCrate {} // Llvm is on a per-thread basis
impl !Sync for LlvmTransCrate {}
impl LlvmTransCrate { impl LlvmTransCrate {
pub fn new() -> Self { pub fn new(sess: &Session) -> Box<TransCrate> {
LlvmTransCrate(()) llvm_util::init(sess); // Make sure llvm is inited
box LlvmTransCrate(())
} }
} }
impl rustc_trans_utils::trans_crate::TransCrate for LlvmTransCrate { impl TransCrate for LlvmTransCrate {
type MetadataLoader = metadata::LlvmMetadataLoader; fn print(&self, req: PrintRequest, sess: &Session) {
type OngoingCrateTranslation = back::write::OngoingCrateTranslation; match req {
type TranslatedCrate = CrateTranslation; PrintRequest::RelocationModels => {
println!("Available relocation models:");
for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
println!(" {}", name);
}
println!("");
}
PrintRequest::CodeModels => {
println!("Available code models:");
for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){
println!(" {}", name);
}
println!("");
}
PrintRequest::TlsModels => {
println!("Available TLS models:");
for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){
println!(" {}", name);
}
println!("");
}
req => llvm_util::print(req, sess),
}
}
fn target_features(&self, sess: &Session) -> Vec<Symbol> {
target_features(sess)
}
fn metadata_loader() -> Box<MetadataLoader> { fn metadata_loader(&self) -> Box<MetadataLoader> {
box metadata::LlvmMetadataLoader box metadata::LlvmMetadataLoader
} }
fn provide(providers: &mut ty::maps::Providers) { fn provide(&self, providers: &mut ty::maps::Providers) {
back::symbol_names::provide(providers); back::symbol_names::provide(providers);
back::symbol_export::provide(providers); back::symbol_export::provide(providers);
base::provide(providers); base::provide(providers);
attributes::provide(providers); attributes::provide(providers);
} }
fn provide_extern(providers: &mut ty::maps::Providers) { fn provide_extern(&self, providers: &mut ty::maps::Providers) {
back::symbol_export::provide_extern(providers); back::symbol_export::provide_extern(providers);
} }
fn trans_crate<'a, 'tcx>( fn trans_crate<'a, 'tcx>(
&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
rx: mpsc::Receiver<Box<Any + Send>> rx: mpsc::Receiver<Box<Any + Send>>
) -> Self::OngoingCrateTranslation { ) -> Box<Any> {
base::trans_crate(tcx, rx) box base::trans_crate(tcx, rx)
} }
fn join_trans( fn join_trans_and_link(
trans: Self::OngoingCrateTranslation, &self,
trans: Box<Any>,
sess: &Session, sess: &Session,
dep_graph: &DepGraph dep_graph: &DepGraph,
) -> Self::TranslatedCrate { outputs: &OutputFilenames,
trans.join(sess, dep_graph) ) -> Result<(), CompileIncomplete>{
use rustc::util::common::time;
let trans = trans.downcast::<::back::write::OngoingCrateTranslation>()
.expect("Expected LlvmTransCrate's OngoingCrateTranslation, found Box<Any>")
.join(sess, dep_graph);
if sess.opts.debugging_opts.incremental_info {
back::write::dump_incremental_data(&trans);
} }
fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) { time(sess.time_passes(),
back::link::link_binary(sess, trans, outputs, &trans.crate_name.as_str()); "serialize work products",
move || rustc_incremental::save_work_products(sess, &dep_graph));
sess.compile_status()?;
if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
i == OutputType::Metadata) {
return Ok(());
} }
fn dump_incremental_data(trans: &Self::TranslatedCrate) { // Run the linker on any artifacts that resulted from the LLVM run.
back::write::dump_incremental_data(trans); // This should produce either a finished executable or library.
time(sess.time_passes(), "linking", || {
back::link::link_binary(sess, &trans, outputs, &trans.crate_name.as_str());
});
// Now that we won't touch anything in the incremental compilation directory
// any more, we can finalize it (which involves renaming it)
rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
Ok(())
} }
} }
......
...@@ -19,11 +19,12 @@ ...@@ -19,11 +19,12 @@
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once; use std::sync::Once;
pub fn init(sess: &Session) { static POISONED: AtomicBool = AtomicBool::new(false);
static INIT: Once = Once::new();
pub(crate) fn init(sess: &Session) {
unsafe { unsafe {
// Before we touch LLVM, make sure that multithreading is enabled. // Before we touch LLVM, make sure that multithreading is enabled.
static POISONED: AtomicBool = AtomicBool::new(false);
static INIT: Once = Once::new();
INIT.call_once(|| { INIT.call_once(|| {
if llvm::LLVMStartMultithreaded() != 1 { if llvm::LLVMStartMultithreaded() != 1 {
// use an extra bool to make sure that all future usage of LLVM // use an extra bool to make sure that all future usage of LLVM
...@@ -40,6 +41,13 @@ pub fn init(sess: &Session) { ...@@ -40,6 +41,13 @@ pub fn init(sess: &Session) {
} }
} }
fn require_inited() {
INIT.call_once(|| bug!("llvm is not initialized"));
if POISONED.load(Ordering::SeqCst) {
bug!("couldn't enable multi-threaded LLVM");
}
}
unsafe fn configure_llvm(sess: &Session) { unsafe fn configure_llvm(sess: &Session) {
let mut llvm_c_strs = Vec::new(); let mut llvm_c_strs = Vec::new();
let mut llvm_args = Vec::new(); let mut llvm_args = Vec::new();
...@@ -125,6 +133,7 @@ pub fn target_feature_whitelist(sess: &Session) -> Vec<&CStr> { ...@@ -125,6 +133,7 @@ pub fn target_feature_whitelist(sess: &Session) -> Vec<&CStr> {
} }
pub fn print_version() { pub fn print_version() {
// Can be called without initializing LLVM
unsafe { unsafe {
println!("LLVM version: {}.{}", println!("LLVM version: {}.{}",
llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor()); llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
...@@ -132,10 +141,12 @@ pub fn print_version() { ...@@ -132,10 +141,12 @@ pub fn print_version() {
} }
pub fn print_passes() { pub fn print_passes() {
// Can be called without initializing LLVM
unsafe { llvm::LLVMRustPrintPasses(); } unsafe { llvm::LLVMRustPrintPasses(); }
} }
pub fn print(req: PrintRequest, sess: &Session) { pub(crate) fn print(req: PrintRequest, sess: &Session) {
require_inited();
let tm = create_target_machine(sess); let tm = create_target_machine(sess);
unsafe { unsafe {
match req { match req {
......
...@@ -25,11 +25,10 @@ ...@@ -25,11 +25,10 @@
use type_of::LayoutLlvmExt; use type_of::LayoutLlvmExt;
use rustc::hir; use rustc::hir;
use rustc::mir::mono::{Linkage, Visibility}; use rustc::mir::mono::{Linkage, Visibility};
use rustc::ty::{TyCtxt, TypeFoldable}; use rustc::ty::TypeFoldable;
use rustc::ty::layout::LayoutOf; use rustc::ty::layout::LayoutOf;
use syntax::ast; use syntax::ast;
use syntax::attr; use syntax::attr;
use syntax_pos::Span;
use std::fmt; use std::fmt;
pub use rustc::mir::mono::MonoItem; pub use rustc::mir::mono::MonoItem;
...@@ -107,18 +106,6 @@ fn predefine(&self, ...@@ -107,18 +106,6 @@ fn predefine(&self,
cx.codegen_unit.name()); cx.codegen_unit.name());
} }
fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
match *self.as_mono_item() {
MonoItem::Fn(Instance { def, .. }) => {
tcx.hir.as_local_node_id(def.def_id())
}
MonoItem::Static(node_id) |
MonoItem::GlobalAsm(node_id) => {
Some(node_id)
}
}.map(|node_id| tcx.hir.span(node_id))
}
fn to_raw_string(&self) -> String { fn to_raw_string(&self) -> String {
match *self.as_mono_item() { match *self.as_mono_item() {
MonoItem::Fn(instance) => { MonoItem::Fn(instance) => {
......
...@@ -19,3 +19,5 @@ syntax_pos = { path = "../libsyntax_pos" } ...@@ -19,3 +19,5 @@ syntax_pos = { path = "../libsyntax_pos" }
rustc = { path = "../librustc" } rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" } rustc_back = { path = "../librustc_back" }
rustc_data_structures = { path = "../librustc_data_structures" } rustc_data_structures = { path = "../librustc_data_structures" }
rustc_mir = { path = "../librustc_mir" }
rustc_incremental = { path = "../librustc_incremental" }
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
...@@ -8,24 +8,31 @@ ...@@ -8,24 +8,31 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use syntax::ast; #![allow(non_snake_case)]
use rustc::session::Session;
use syntax::symbol::Symbol; register_long_diagnostics! {
use rustc_trans;
E0558: r##"
/// Add `target_feature = "..."` cfgs for a variety of platform The `export_name` attribute was malformed.
/// specific features (SSE, NEON etc.).
/// Erroneous code example:
/// This is performed by checking whether a whitelisted set of
/// features is available on the target machine, by querying LLVM. ```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) { #[export_name] // error: export_name attribute has invalid format
let tf = Symbol::intern("target_feature"); pub fn something() {}
for feat in rustc_trans::target_features(sess) { fn main() {}
cfg.insert((tf, Some(feat))); ```
}
The `export_name` attribute expects a string in order to determine the name of
if sess.crt_static_feature() { the exported symbol. Example:
cfg.insert((tf, Some(Symbol::intern("crt-static"))));
} ```
#[export_name = "some_function"] // ok!
pub fn something() {}
fn main() {}
```
"##,
} }
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
#[macro_use] #[macro_use]
extern crate rustc; extern crate rustc;
extern crate rustc_back; extern crate rustc_back;
extern crate rustc_mir;
extern crate rustc_incremental;
#[macro_use]
extern crate syntax; extern crate syntax;
extern crate syntax_pos; extern crate syntax_pos;
extern crate rustc_data_structures; extern crate rustc_data_structures;
...@@ -45,8 +48,11 @@ ...@@ -45,8 +48,11 @@
use rustc::hir::map as hir_map; use rustc::hir::map as hir_map;
use rustc::util::nodemap::NodeSet; use rustc::util::nodemap::NodeSet;
pub mod diagnostics;
pub mod link; pub mod link;
pub mod trans_crate; pub mod trans_crate;
pub mod symbol_names;
pub mod symbol_names_test;
/// check for the #[rustc_error] annotation, which forces an /// check for the #[rustc_error] annotation, which forces an
/// error in trans. This is used to write compile-fail tests /// error in trans. This is used to write compile-fail tests
...@@ -110,3 +116,5 @@ pub fn find_exported_symbols<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet { ...@@ -110,3 +116,5 @@ pub fn find_exported_symbols<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet {
} }
}).collect() }).collect()
} }
__build_diagnostic_array! { librustc_trans_utils, DIAGNOSTICS }
...@@ -97,11 +97,9 @@ ...@@ -97,11 +97,9 @@
//! virtually impossible. Thus, symbol hash generation exclusively relies on //! virtually impossible. Thus, symbol hash generation exclusively relies on
//! DefPaths which are much more robust in the face of changes to the code base. //! DefPaths which are much more robust in the face of changes to the code base.
use monomorphize::Instance;
use trans_item::{BaseMonoItemExt, InstantiationMode};
use rustc::middle::weak_lang_items; use rustc::middle::weak_lang_items;
use rustc::mir::mono::MonoItem; use rustc_mir::monomorphize::Instance;
use rustc_mir::monomorphize::item::{MonoItem, MonoItemExt, InstantiationMode};
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::hir::map as hir_map; use rustc::hir::map as hir_map;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
use rustc::ty::TyCtxt; use rustc::ty::TyCtxt;
use syntax::ast; use syntax::ast;
use monomorphize::Instance; use rustc_mir::monomorphize::Instance;
const SYMBOL_NAME: &'static str = "rustc_symbol_name"; const SYMBOL_NAME: &'static str = "rustc_symbol_name";
const ITEM_PATH: &'static str = "rustc_item_path"; const ITEM_PATH: &'static str = "rustc_item_path";
......
...@@ -35,83 +35,81 @@ ...@@ -35,83 +35,81 @@
use syntax::symbol::Symbol; use syntax::symbol::Symbol;
use rustc::hir::def_id::LOCAL_CRATE; use rustc::hir::def_id::LOCAL_CRATE;
use rustc::session::Session; use rustc::session::{Session, CompileIncomplete};
use rustc::session::config::{CrateType, OutputFilenames}; use rustc::session::config::{CrateType, OutputFilenames, PrintRequest};
use rustc::ty::TyCtxt; use rustc::ty::TyCtxt;
use rustc::ty::maps::Providers; use rustc::ty::maps::Providers;
use rustc::middle::cstore::EncodedMetadata; use rustc::middle::cstore::EncodedMetadata;
use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait; use rustc::middle::cstore::MetadataLoader as MetadataLoader;
use rustc::dep_graph::DepGraph; use rustc::dep_graph::DepGraph;
use rustc_back::target::Target; use rustc_back::target::Target;
use rustc_mir::monomorphize::collector;
use link::{build_link_meta, out_filename}; use link::{build_link_meta, out_filename};
pub trait TransCrate { pub trait TransCrate {
type MetadataLoader: MetadataLoaderTrait; fn print(&self, _req: PrintRequest, _sess: &Session) {}
type OngoingCrateTranslation; fn target_features(&self, _sess: &Session) -> Vec<Symbol> { vec![] }
type TranslatedCrate;
fn metadata_loader() -> Box<MetadataLoaderTrait>; fn metadata_loader(&self) -> Box<MetadataLoader>;
fn provide(_providers: &mut Providers); fn provide(&self, _providers: &mut Providers);
fn provide_extern(_providers: &mut Providers); fn provide_extern(&self, _providers: &mut Providers);
fn trans_crate<'a, 'tcx>( fn trans_crate<'a, 'tcx>(
&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
rx: mpsc::Receiver<Box<Any + Send>> rx: mpsc::Receiver<Box<Any + Send>>
) -> Self::OngoingCrateTranslation; ) -> Box<Any>;
fn join_trans(
trans: Self::OngoingCrateTranslation, /// This is called on the returned `Box<Any>` from `trans_crate`
///
/// # Panics
///
/// Panics when the passed `Box<Any>` was not returned by `trans_crate`.
fn join_trans_and_link(
&self,
trans: Box<Any>,
sess: &Session, sess: &Session,
dep_graph: &DepGraph dep_graph: &DepGraph,
) -> Self::TranslatedCrate; outputs: &OutputFilenames,
fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames); ) -> Result<(), CompileIncomplete>;
fn dump_incremental_data(trans: &Self::TranslatedCrate);
} }
pub struct DummyTransCrate; pub struct DummyTransCrate;
impl TransCrate for DummyTransCrate { impl TransCrate for DummyTransCrate {
type MetadataLoader = DummyMetadataLoader; fn metadata_loader(&self) -> Box<MetadataLoader> {
type OngoingCrateTranslation = ();
type TranslatedCrate = ();
fn metadata_loader() -> Box<MetadataLoaderTrait> {
box DummyMetadataLoader(()) box DummyMetadataLoader(())
} }
fn provide(_providers: &mut Providers) { fn provide(&self, _providers: &mut Providers) {
bug!("DummyTransCrate::provide"); bug!("DummyTransCrate::provide");
} }
fn provide_extern(_providers: &mut Providers) { fn provide_extern(&self, _providers: &mut Providers) {
bug!("DummyTransCrate::provide_extern"); bug!("DummyTransCrate::provide_extern");
} }
fn trans_crate<'a, 'tcx>( fn trans_crate<'a, 'tcx>(
&self,
_tcx: TyCtxt<'a, 'tcx, 'tcx>, _tcx: TyCtxt<'a, 'tcx, 'tcx>,
_rx: mpsc::Receiver<Box<Any + Send>> _rx: mpsc::Receiver<Box<Any + Send>>
) -> Self::OngoingCrateTranslation { ) -> Box<Any> {
bug!("DummyTransCrate::trans_crate"); bug!("DummyTransCrate::trans_crate");
} }
fn join_trans( fn join_trans_and_link(
_trans: Self::OngoingCrateTranslation, &self,
_trans: Box<Any>,
_sess: &Session, _sess: &Session,
_dep_graph: &DepGraph _dep_graph: &DepGraph,
) -> Self::TranslatedCrate { _outputs: &OutputFilenames,
bug!("DummyTransCrate::join_trans"); ) -> Result<(), CompileIncomplete> {
} bug!("DummyTransCrate::join_trans_and_link");
fn link_binary(_sess: &Session, _trans: &Self::TranslatedCrate, _outputs: &OutputFilenames) {
bug!("DummyTransCrate::link_binary");
}
fn dump_incremental_data(_trans: &Self::TranslatedCrate) {
bug!("DummyTransCrate::dump_incremental_data");
} }
} }
pub struct DummyMetadataLoader(()); pub struct DummyMetadataLoader(());
impl MetadataLoaderTrait for DummyMetadataLoader { impl MetadataLoader for DummyMetadataLoader {
fn get_rlib_metadata( fn get_rlib_metadata(
&self, &self,
_target: &Target, _target: &Target,
...@@ -131,7 +129,7 @@ fn get_dylib_metadata( ...@@ -131,7 +129,7 @@ fn get_dylib_metadata(
pub struct NoLlvmMetadataLoader; pub struct NoLlvmMetadataLoader;
impl MetadataLoaderTrait for NoLlvmMetadataLoader { impl MetadataLoader for NoLlvmMetadataLoader {
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> { fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
let file = File::open(filename) let file = File::open(filename)
.map_err(|e| format!("metadata file open err: {:?}", e))?; .map_err(|e| format!("metadata file open err: {:?}", e))?;
...@@ -161,87 +159,131 @@ fn get_dylib_metadata( ...@@ -161,87 +159,131 @@ fn get_dylib_metadata(
} }
} }
pub struct MetadataOnlyTransCrate; pub struct MetadataOnlyTransCrate(());
pub struct OngoingCrateTranslation { pub struct OngoingCrateTranslation {
metadata: EncodedMetadata, metadata: EncodedMetadata,
metadata_version: Vec<u8>, metadata_version: Vec<u8>,
crate_name: Symbol, crate_name: Symbol,
} }
pub struct TranslatedCrate(OngoingCrateTranslation);
impl MetadataOnlyTransCrate { impl MetadataOnlyTransCrate {
#[allow(dead_code)] pub fn new(sess: &Session) -> Box<TransCrate> {
pub fn new() -> Self { for cty in sess.opts.crate_types.iter() {
MetadataOnlyTransCrate match *cty {
CrateType::CrateTypeRlib | CrateType::CrateTypeDylib |
CrateType::CrateTypeExecutable => {},
_ => {
sess.parse_sess.span_diagnostic.warn(
&format!("LLVM unsupported, so output type {} is not supported", cty)
);
},
}
}
box MetadataOnlyTransCrate(())
} }
} }
impl TransCrate for MetadataOnlyTransCrate { impl TransCrate for MetadataOnlyTransCrate {
type MetadataLoader = NoLlvmMetadataLoader; fn metadata_loader(&self) -> Box<MetadataLoader> {
type OngoingCrateTranslation = OngoingCrateTranslation;
type TranslatedCrate = TranslatedCrate;
fn metadata_loader() -> Box<MetadataLoaderTrait> {
box NoLlvmMetadataLoader box NoLlvmMetadataLoader
} }
fn provide(_providers: &mut Providers) {} fn provide(&self, providers: &mut Providers) {
fn provide_extern(_providers: &mut Providers) {} ::symbol_names::provide(providers);
}
fn provide_extern(&self, _providers: &mut Providers) {}
fn trans_crate<'a, 'tcx>( fn trans_crate<'a, 'tcx>(
&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
_rx: mpsc::Receiver<Box<Any + Send>> _rx: mpsc::Receiver<Box<Any + Send>>
) -> Self::OngoingCrateTranslation { ) -> Box<Any> {
use rustc_mir::monomorphize::item::MonoItem;
::check_for_rustc_errors_attr(tcx); ::check_for_rustc_errors_attr(tcx);
::symbol_names_test::report_symbol_names(tcx);
::rustc_incremental::assert_dep_graph(tcx);
::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx,
collector::collect_crate_mono_items(
tcx,
collector::MonoItemCollectionMode::Eager
).0.iter()
);
::rustc::middle::dependency_format::calculate(tcx);
let _ = tcx.link_args(LOCAL_CRATE); let _ = tcx.link_args(LOCAL_CRATE);
let _ = tcx.native_libraries(LOCAL_CRATE); let _ = tcx.native_libraries(LOCAL_CRATE);
for trans_item in
collector::collect_crate_mono_items(
tcx,
collector::MonoItemCollectionMode::Eager
).0 {
match trans_item {
MonoItem::Fn(inst) => {
let def_id = inst.def_id();
if def_id.is_local() {
let _ = tcx.export_name(def_id);
let _ = tcx.contains_extern_indicator(def_id);
let _ = inst.def.is_inline(tcx);
let attrs = inst.def.attrs(tcx);
let _ =
::syntax::attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs);
}
}
_ => {}
}
}
tcx.sess.abort_if_errors(); tcx.sess.abort_if_errors();
let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE)); let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE));
let exported_symbols = ::find_exported_symbols(tcx); let exported_symbols = ::find_exported_symbols(tcx);
let metadata = tcx.encode_metadata(&link_meta, &exported_symbols); let metadata = tcx.encode_metadata(&link_meta, &exported_symbols);
OngoingCrateTranslation { box OngoingCrateTranslation {
metadata: metadata, metadata: metadata,
metadata_version: tcx.metadata_encoding_version().to_vec(), metadata_version: tcx.metadata_encoding_version().to_vec(),
crate_name: tcx.crate_name(LOCAL_CRATE), crate_name: tcx.crate_name(LOCAL_CRATE),
} }
} }
fn join_trans( fn join_trans_and_link(
trans: Self::OngoingCrateTranslation, &self,
_sess: &Session, trans: Box<Any>,
sess: &Session,
_dep_graph: &DepGraph, _dep_graph: &DepGraph,
) -> Self::TranslatedCrate { outputs: &OutputFilenames,
TranslatedCrate(trans) ) -> Result<(), CompileIncomplete> {
} let trans = trans.downcast::<OngoingCrateTranslation>()
.expect("Expected MetadataOnlyTransCrate's OngoingCrateTranslation, found Box<Any>");
fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) {
for &crate_type in sess.opts.crate_types.iter() { for &crate_type in sess.opts.crate_types.iter() {
if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib { if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib {
continue; continue;
} }
let output_name = let output_name =
out_filename(sess, crate_type, &outputs, &trans.0.crate_name.as_str()); out_filename(sess, crate_type, &outputs, &trans.crate_name.as_str());
let mut compressed = trans.0.metadata_version.clone(); let mut compressed = trans.metadata_version.clone();
let metadata = if crate_type == CrateType::CrateTypeDylib { let metadata = if crate_type == CrateType::CrateTypeDylib {
DeflateEncoder::new(&mut compressed, Compression::fast()) DeflateEncoder::new(&mut compressed, Compression::fast())
.write_all(&trans.0.metadata.raw_data) .write_all(&trans.metadata.raw_data)
.unwrap(); .unwrap();
&compressed &compressed
} else { } else {
&trans.0.metadata.raw_data &trans.metadata.raw_data
}; };
let mut builder = Builder::new(File::create(&output_name).unwrap()); let mut builder = Builder::new(File::create(&output_name).unwrap());
let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64); let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64);
builder.append(&header, Cursor::new(metadata)).unwrap(); builder.append(&header, Cursor::new(metadata)).unwrap();
} }
sess.abort_if_errors();
if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib) if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib)
&& !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) { && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib)
// Don't error when running under compiletest
&& ::std::env::var("RUSTC_COMPILETEST") != Ok("1".to_string())
{
sess.fatal("Executables are not supported by the metadata-only backend."); sess.fatal("Executables are not supported by the metadata-only backend.");
} }
Ok(())
} }
fn dump_incremental_data(_trans: &Self::TranslatedCrate) {}
} }
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
use rustc::lint; use rustc::lint;
use rustc::util::nodemap::FxHashMap; use rustc::util::nodemap::FxHashMap;
use rustc_trans; use rustc_trans;
use rustc_trans::back::link;
use rustc_resolve as resolve; use rustc_resolve as resolve;
use rustc_metadata::cstore::CStore; use rustc_metadata::cstore::CStore;
...@@ -140,22 +139,22 @@ pub fn run_core(search_paths: SearchPaths, ...@@ -140,22 +139,22 @@ pub fn run_core(search_paths: SearchPaths,
false, false,
Some(codemap.clone())); Some(codemap.clone()));
let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
let mut sess = session::build_session_( let mut sess = session::build_session_(
sessopts, cpath, diagnostic_handler, codemap, sessopts, cpath, diagnostic_handler, codemap,
); );
rustc_trans::init(&sess); let trans = rustc_trans::LlvmTransCrate::new(&sess);
let cstore = Rc::new(CStore::new(trans.metadata_loader()));
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs)); let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs));
target_features::add_configuration(&mut cfg, &sess); target_features::add_configuration(&mut cfg, &sess, &*trans);
sess.parse_sess.config = cfg; sess.parse_sess.config = cfg;
let control = &driver::CompileController::basic(); let control = &driver::CompileController::basic();
let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input)); let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input));
let name = link::find_crate_name(Some(&sess), &krate.attrs, &input); let name = ::rustc_trans_utils::link::find_crate_name(Some(&sess), &krate.attrs, &input);
let driver::ExpansionResult { defs, analysis, resolutions, mut hir_forest, .. } = { let driver::ExpansionResult { defs, analysis, resolutions, mut hir_forest, .. } = {
let result = driver::phase_2_configure_and_expand(&sess, let result = driver::phase_2_configure_and_expand(&sess,
...@@ -177,7 +176,8 @@ pub fn run_core(search_paths: SearchPaths, ...@@ -177,7 +176,8 @@ pub fn run_core(search_paths: SearchPaths,
&[], &[],
&sess); &sess);
abort_on_err(driver::phase_3_run_analysis_passes(control, abort_on_err(driver::phase_3_run_analysis_passes(&*trans,
control,
&sess, &sess,
&*cstore, &*cstore,
hir_map, hir_map,
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
extern crate rustc; extern crate rustc;
extern crate rustc_data_structures; extern crate rustc_data_structures;
extern crate rustc_const_math; extern crate rustc_const_math;
extern crate rustc_trans; extern crate rustc_trans_utils;
extern crate rustc_driver; extern crate rustc_driver;
extern crate rustc_resolve; extern crate rustc_resolve;
extern crate rustc_lint; extern crate rustc_lint;
...@@ -63,6 +63,8 @@ ...@@ -63,6 +63,8 @@
use std::process; use std::process;
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
use rustc_driver::rustc_trans;
use externalfiles::ExternalHtml; use externalfiles::ExternalHtml;
use rustc::session::search_paths::SearchPaths; use rustc::session::search_paths::SearchPaths;
use rustc::session::config::{ErrorOutputType, RustcOptGroup, nightly_options, use rustc::session::config::{ErrorOutputType, RustcOptGroup, nightly_options,
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
use rustc_metadata::cstore::CStore; use rustc_metadata::cstore::CStore;
use rustc_resolve::MakeGlobMap; use rustc_resolve::MakeGlobMap;
use rustc_trans; use rustc_trans;
use rustc_trans::back::link;
use syntax::ast; use syntax::ast;
use syntax::codemap::CodeMap; use syntax::codemap::CodeMap;
use syntax::feature_gate::UnstableFeatures; use syntax::feature_gate::UnstableFeatures;
...@@ -82,11 +81,11 @@ pub fn run(input_path: &Path, ...@@ -82,11 +81,11 @@ pub fn run(input_path: &Path,
true, false, true, false,
Some(codemap.clone())); Some(codemap.clone()));
let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
let mut sess = session::build_session_( let mut sess = session::build_session_(
sessopts, Some(input_path.to_owned()), handler, codemap.clone(), sessopts, Some(input_path.to_owned()), handler, codemap.clone(),
); );
rustc_trans::init(&sess); let trans = rustc_trans::LlvmTransCrate::new(&sess);
let cstore = Rc::new(CStore::new(trans.metadata_loader()));
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
sess.parse_sess.config = sess.parse_sess.config =
config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone())); config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
...@@ -108,7 +107,7 @@ pub fn run(input_path: &Path, ...@@ -108,7 +107,7 @@ pub fn run(input_path: &Path,
}; };
let crate_name = crate_name.unwrap_or_else(|| { let crate_name = crate_name.unwrap_or_else(|| {
link::find_crate_name(None, &hir_forest.krate().attrs, &input) ::rustc_trans_utils::link::find_crate_name(None, &hir_forest.krate().attrs, &input)
}); });
let opts = scrape_test_config(hir_forest.krate()); let opts = scrape_test_config(hir_forest.krate());
let mut collector = Collector::new(crate_name, let mut collector = Collector::new(crate_name,
...@@ -247,11 +246,11 @@ fn drop(&mut self) { ...@@ -247,11 +246,11 @@ fn drop(&mut self) {
// Compile the code // Compile the code
let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter); let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter);
let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
let mut sess = session::build_session_( let mut sess = session::build_session_(
sessopts, None, diagnostic_handler, codemap, sessopts, None, diagnostic_handler, codemap,
); );
rustc_trans::init(&sess); let trans = rustc_trans::LlvmTransCrate::new(&sess);
let cstore = Rc::new(CStore::new(trans.metadata_loader()));
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir")); let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"));
...@@ -266,7 +265,17 @@ fn drop(&mut self) { ...@@ -266,7 +265,17 @@ fn drop(&mut self) {
} }
let res = panic::catch_unwind(AssertUnwindSafe(|| { let res = panic::catch_unwind(AssertUnwindSafe(|| {
driver::compile_input(&sess, &cstore, &None, &input, &out, &None, None, &control) driver::compile_input(
trans,
&sess,
&cstore,
&None,
&input,
&out,
&None,
None,
&control
)
})); }));
let compile_result = match res { let compile_result = match res {
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
extern crate rustc_metadata; extern crate rustc_metadata;
extern crate rustc_errors; extern crate rustc_errors;
extern crate rustc_trans; extern crate rustc_trans;
extern crate rustc_trans_utils;
extern crate syntax; extern crate syntax;
use rustc::session::{build_session, Session}; use rustc::session::{build_session, Session};
...@@ -25,6 +26,7 @@ ...@@ -25,6 +26,7 @@
use rustc_metadata::cstore::CStore; use rustc_metadata::cstore::CStore;
use rustc_errors::registry::Registry; use rustc_errors::registry::Registry;
use syntax::codemap::FileName; use syntax::codemap::FileName;
use rustc_trans_utils::trans_crate::TransCrate;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
...@@ -51,7 +53,7 @@ fn main() {} ...@@ -51,7 +53,7 @@ fn main() {}
compile(src.to_string(), tmpdir.join("out"), sysroot.clone()); compile(src.to_string(), tmpdir.join("out"), sysroot.clone());
} }
fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) { fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>, Box<TransCrate>) {
let mut opts = basic_options(); let mut opts = basic_options();
opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]); opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
opts.maybe_sysroot = Some(sysroot); opts.maybe_sysroot = Some(sysroot);
...@@ -60,16 +62,26 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) { ...@@ -60,16 +62,26 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
} }
let descriptions = Registry::new(&rustc::DIAGNOSTICS); let descriptions = Registry::new(&rustc::DIAGNOSTICS);
let cstore = Rc::new(CStore::new(Box::new(rustc_trans::LlvmMetadataLoader)));
let sess = build_session(opts, None, descriptions); let sess = build_session(opts, None, descriptions);
rustc_trans::init(&sess); let trans = rustc_trans::LlvmTransCrate::new(&sess);
let cstore = Rc::new(CStore::new(trans.metadata_loader()));
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
(sess, cstore) (sess, cstore, trans)
} }
fn compile(code: String, output: PathBuf, sysroot: PathBuf) { fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
let (sess, cstore) = basic_sess(sysroot); let (sess, cstore, trans) = basic_sess(sysroot);
let control = CompileController::basic(); let control = CompileController::basic();
let input = Input::Str { name: FileName::Anon, input: code }; let input = Input::Str { name: FileName::Anon, input: code };
let _ = compile_input(&sess, &cstore, &None, &input, &None, &Some(output), None, &control); let _ = compile_input(
trans,
&sess,
&cstore,
&None,
&input,
&None,
&Some(output),
None,
&control
);
} }
-include ../tools.mk
all:
$(RUSTC) test.rs
$(call RUN,test $(RUSTC))
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(plugin, rustc_private, box_syntax)]
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_llvm;
extern crate rustc_trans;
#[macro_use] extern crate syntax;
extern crate getopts;
use rustc_driver::{CompilerCalls, Compilation};
use rustc_driver::driver::CompileController;
use rustc_trans::ModuleSource;
use rustc::session::Session;
use syntax::codemap::FileLoader;
use std::env;
use std::io;
use std::path::{PathBuf, Path};
struct JitLoader;
impl FileLoader for JitLoader {
fn file_exists(&self, _: &Path) -> bool { true }
fn abs_path(&self, _: &Path) -> Option<PathBuf> { None }
fn read_file(&self, _: &Path) -> io::Result<String> {
Ok(r#"
#[no_mangle]
pub fn test_add(a: i32, b: i32) -> i32 { a + b }
"#.to_string())
}
}
#[derive(Copy, Clone)]
struct JitCalls;
impl<'a> CompilerCalls<'a> for JitCalls {
fn build_controller(&mut self,
_: &Session,
_: &getopts::Matches)
-> CompileController<'a> {
let mut cc = CompileController::basic();
cc.after_llvm.stop = Compilation::Stop;
cc.after_llvm.run_callback_on_error = true;
cc.after_llvm.callback = Box::new(|state| {
state.session.abort_if_errors();
let trans = state.trans.unwrap();
assert_eq!(trans.modules.len(), 1);
println!("name of compiled module = {}", trans.modules[0].name);
});
cc
}
}
fn main() {
use rustc_driver;
let mut path = match std::env::args().nth(2) {
Some(path) => PathBuf::from(&path),
None => panic!("missing rustc path")
};
// Remove two segments from rustc path to get sysroot.
path.pop();
path.pop();
let mut args: Vec<String> =
format!("_ _ --sysroot {} --crate-type dylib", path.to_str().unwrap())
.split(' ').map(|s| s.to_string()).collect();
args.push("--out-dir".to_string());
args.push(env::var("TMPDIR").unwrap());
args.push("-Ccodegen-units=1".to_string());
let (result, _) = rustc_driver::run_compiler(
&args, &mut JitCalls, Some(box JitLoader), None);
if let Err(n) = result {
panic!("Error {:?}", n);
}
}
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
extern crate getopts; extern crate getopts;
extern crate rustc; extern crate rustc;
extern crate rustc_driver; extern crate rustc_driver;
extern crate rustc_trans_utils;
extern crate syntax; extern crate syntax;
extern crate rustc_errors as errors; extern crate rustc_errors as errors;
...@@ -25,6 +26,7 @@ ...@@ -25,6 +26,7 @@
use rustc::session::Session; use rustc::session::Session;
use rustc::session::config::{self, Input}; use rustc::session::config::{self, Input};
use rustc_driver::{driver, CompilerCalls, Compilation}; use rustc_driver::{driver, CompilerCalls, Compilation};
use rustc_trans_utils::trans_crate::TransCrate;
use syntax::ast; use syntax::ast;
use std::path::PathBuf; use std::path::PathBuf;
...@@ -46,6 +48,7 @@ fn early_callback(&mut self, ...@@ -46,6 +48,7 @@ fn early_callback(&mut self,
} }
fn late_callback(&mut self, fn late_callback(&mut self,
_: &TransCrate,
_: &getopts::Matches, _: &getopts::Matches,
_: &Session, _: &Session,
_: &CrateStore, _: &CrateStore,
......
...@@ -1278,7 +1278,7 @@ fn compile_test(&self) -> ProcRes { ...@@ -1278,7 +1278,7 @@ fn compile_test(&self) -> ProcRes {
TargetLocation::ThisFile(self.make_exe_name()), TargetLocation::ThisFile(self.make_exe_name()),
); );
rustc.arg("-L").arg(&self.aux_output_dir_name()); rustc.arg("-L").arg(&self.aux_output_dir_name()).env("RUSTC_COMPILETEST", "1");
match self.config.mode { match self.config.mode {
CompileFail | Ui => { CompileFail | Ui => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册