mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #45684 - bjorn3:runtime_choose_trans2, r=eddyb
Allow runtime switching between trans backends The driver callback after_llvm has been removed as it doesnt work with multiple backends. r? @eddyb
This commit is contained in:
commit
9368a1e3e2
3
src/Cargo.lock
generated
3
src/Cargo.lock
generated
@ -2010,7 +2010,6 @@ dependencies = [
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_trans_utils 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
@ -2133,6 +2132,8 @@ dependencies = [
|
||||
"rustc 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_incremental 0.0.0",
|
||||
"rustc_mir 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
@ -1045,6 +1045,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
|
||||
options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||
build_debugging_options, "Z", "debugging",
|
||||
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],
|
||||
"in general, enable more debug printouts"),
|
||||
span_free_formats: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
@ -31,7 +31,6 @@ use rustc_incremental;
|
||||
use rustc_resolve::{MakeGlobMap, Resolver};
|
||||
use rustc_metadata::creader::CrateLoader;
|
||||
use rustc_metadata::cstore::{self, CStore};
|
||||
use rustc_trans as trans;
|
||||
use rustc_trans_utils::trans_crate::TransCrate;
|
||||
use rustc_typeck as typeck;
|
||||
use rustc_privacy;
|
||||
@ -40,7 +39,6 @@ use rustc_plugin as plugin;
|
||||
use rustc_passes::{self, ast_validation, loops, consts, static_recursion, hir_stats};
|
||||
use rustc_const_eval::{self, check_match};
|
||||
use super::Compilation;
|
||||
use ::DefaultTransCrate;
|
||||
|
||||
use serialize::json;
|
||||
|
||||
@ -68,7 +66,8 @@ use pretty::ReplaceBodyWithLoop;
|
||||
|
||||
use profile;
|
||||
|
||||
pub fn compile_input(sess: &Session,
|
||||
pub fn compile_input(trans: Box<TransCrate>,
|
||||
sess: &Session,
|
||||
cstore: &CStore,
|
||||
input_path: &Option<PathBuf>,
|
||||
input: &Input,
|
||||
@ -76,8 +75,6 @@ pub fn compile_input(sess: &Session,
|
||||
output: &Option<PathBuf>,
|
||||
addl_plugins: Option<Vec<String>>,
|
||||
control: &CompileController) -> CompileResult {
|
||||
use rustc::session::config::CrateType;
|
||||
|
||||
macro_rules! controller_entry_point {
|
||||
($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
|
||||
let state = &mut $make_state;
|
||||
@ -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() {
|
||||
profile::begin();
|
||||
}
|
||||
@ -117,7 +98,7 @@ pub fn compile_input(sess: &Session,
|
||||
// We need nested scopes here, because the intermediate results can keep
|
||||
// large chunks of memory alive and we want to free them as soon as
|
||||
// possible to keep the peak memory usage low
|
||||
let (outputs, trans, dep_graph) = {
|
||||
let (outputs, ongoing_trans, dep_graph) = {
|
||||
let krate = match phase_1_parse_input(control, sess, input) {
|
||||
Ok(krate) => krate,
|
||||
Err(mut parse_error) => {
|
||||
@ -217,7 +198,8 @@ pub fn compile_input(sess: &Session,
|
||||
None
|
||||
};
|
||||
|
||||
phase_3_run_analysis_passes(control,
|
||||
phase_3_run_analysis_passes(&*trans,
|
||||
control,
|
||||
sess,
|
||||
cstore,
|
||||
hir_map,
|
||||
@ -254,7 +236,7 @@ pub fn compile_input(sess: &Session,
|
||||
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) {
|
||||
println!("Post-trans");
|
||||
@ -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,
|
||||
sess.code_stats.borrow().print_type_sizes();
|
||||
}
|
||||
|
||||
let (phase5_result, trans) =
|
||||
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);
|
||||
trans.join_trans_and_link(ongoing_trans, sess, &dep_graph, &outputs)?;
|
||||
|
||||
if sess.opts.debugging_opts.perf_stats {
|
||||
sess.print_perf_stats();
|
||||
@ -340,7 +304,6 @@ pub struct CompileController<'a> {
|
||||
pub after_expand: PhaseController<'a>,
|
||||
pub after_hir_lowering: PhaseController<'a>,
|
||||
pub after_analysis: PhaseController<'a>,
|
||||
pub after_llvm: PhaseController<'a>,
|
||||
pub compilation_done: PhaseController<'a>,
|
||||
|
||||
// FIXME we probably want to group the below options together and offer a
|
||||
@ -366,7 +329,6 @@ impl<'a> CompileController<'a> {
|
||||
after_expand: PhaseController::basic(),
|
||||
after_hir_lowering: PhaseController::basic(),
|
||||
after_analysis: PhaseController::basic(),
|
||||
after_llvm: PhaseController::basic(),
|
||||
compilation_done: PhaseController::basic(),
|
||||
make_glob_map: MakeGlobMap::No,
|
||||
keep_ast: false,
|
||||
@ -415,7 +377,6 @@ pub struct CompileState<'a, 'tcx: 'a> {
|
||||
pub resolutions: Option<&'a Resolutions>,
|
||||
pub analysis: Option<&'a ty::CrateAnalysis>,
|
||||
pub tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
|
||||
pub trans: Option<&'a trans::CrateTranslation>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> CompileState<'a, 'tcx> {
|
||||
@ -440,7 +401,6 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
|
||||
resolutions: None,
|
||||
analysis: None,
|
||||
tcx: None,
|
||||
trans: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -528,19 +488,6 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
session: &'tcx Session,
|
||||
out_dir: &'a Option<PathBuf>,
|
||||
@ -933,7 +880,6 @@ pub fn default_provide(providers: &mut ty::maps::Providers) {
|
||||
reachable::provide(providers);
|
||||
resolve_lifetime::provide(providers);
|
||||
rustc_privacy::provide(providers);
|
||||
DefaultTransCrate::provide(providers);
|
||||
typeck::provide(providers);
|
||||
ty::provide(providers);
|
||||
traits::provide(providers);
|
||||
@ -947,13 +893,13 @@ pub fn default_provide(providers: &mut ty::maps::Providers) {
|
||||
|
||||
pub fn default_provide_extern(providers: &mut ty::maps::Providers) {
|
||||
cstore::provide_extern(providers);
|
||||
DefaultTransCrate::provide_extern(providers);
|
||||
}
|
||||
|
||||
/// 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<'tcx, F, R>(control: &CompileController,
|
||||
pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate,
|
||||
control: &CompileController,
|
||||
sess: &'tcx Session,
|
||||
cstore: &'tcx CrateStore,
|
||||
hir_map: hir_map::Map<'tcx>,
|
||||
@ -1006,10 +952,12 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController,
|
||||
|
||||
let mut local_providers = ty::maps::Providers::default();
|
||||
default_provide(&mut local_providers);
|
||||
trans.provide(&mut local_providers);
|
||||
(control.provide)(&mut local_providers);
|
||||
|
||||
let mut extern_providers = local_providers;
|
||||
default_provide_extern(&mut extern_providers);
|
||||
trans.provide_extern(&mut extern_providers);
|
||||
(control.provide_extern)(&mut extern_providers);
|
||||
|
||||
let (tx, rx) = mpsc::channel();
|
||||
@ -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
|
||||
/// 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>>)
|
||||
-> <Trans as TransCrate>::OngoingCrateTranslation {
|
||||
-> Box<Any> {
|
||||
let time_passes = tcx.sess.time_passes();
|
||||
|
||||
time(time_passes,
|
||||
@ -1112,7 +1061,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 't
|
||||
|
||||
let translation =
|
||||
time(time_passes, "translation", move || {
|
||||
Trans::trans_crate(tcx, rx)
|
||||
trans.trans_crate(tcx, rx)
|
||||
});
|
||||
if tcx.sess.profile_queries() {
|
||||
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
|
||||
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 {
|
||||
// Apparently clang and gcc *only* escape spaces:
|
||||
// http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
|
||||
|
@ -48,7 +48,7 @@ extern crate rustc_mir;
|
||||
extern crate rustc_resolve;
|
||||
extern crate rustc_save_analysis;
|
||||
#[cfg(feature="llvm")]
|
||||
extern crate rustc_trans;
|
||||
pub extern crate rustc_trans;
|
||||
extern crate rustc_trans_utils;
|
||||
extern crate rustc_typeck;
|
||||
extern crate serialize;
|
||||
@ -66,7 +66,7 @@ use rustc_save_analysis as save;
|
||||
use rustc_save_analysis::DumpHandler;
|
||||
use rustc::session::{self, config, Session, build_session, CompileResult};
|
||||
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::{early_error, early_warn};
|
||||
use rustc::lint::Lint;
|
||||
@ -106,9 +106,32 @@ mod test;
|
||||
pub mod profile;
|
||||
pub mod driver;
|
||||
pub mod pretty;
|
||||
pub mod target_features;
|
||||
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.\
|
||||
md#bug-reports";
|
||||
|
||||
@ -159,25 +182,51 @@ pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as DefaultTransCr
|
||||
pub use rustc_trans::LlvmTransCrate as DefaultTransCrate;
|
||||
|
||||
#[cfg(not(feature="llvm"))]
|
||||
mod rustc_trans {
|
||||
use syntax_pos::symbol::Symbol;
|
||||
use rustc::session::Session;
|
||||
use rustc::session::config::PrintRequest;
|
||||
pub mod rustc_trans {
|
||||
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_passes() {}
|
||||
pub fn print(_req: PrintRequest, _sess: &Session) {}
|
||||
pub fn target_features(_sess: &Session) -> Vec<Symbol> { vec![] }
|
||||
}
|
||||
|
||||
pub mod back {
|
||||
pub mod write {
|
||||
pub const RELOC_MODEL_ARGS: [(&'static str, ()); 0] = [];
|
||||
pub const CODE_GEN_MODEL_ARGS: [(&'static str, ()); 0] = [];
|
||||
pub const TLS_MODEL_ARGS: [(&'static str, ()); 0] = [];
|
||||
fn load_backend_from_dylib(sess: &Session, backend_name: &str) -> Box<TransCrate> {
|
||||
use std::path::Path;
|
||||
use rustc_metadata::dynamic_lib::DynamicLibrary;
|
||||
|
||||
match DynamicLibrary::open(Some(Path::new(backend_name))) {
|
||||
Ok(lib) => {
|
||||
unsafe {
|
||||
let trans = {
|
||||
let __rustc_codegen_backend: unsafe fn(&Session) -> Box<TransCrate>;
|
||||
__rustc_codegen_backend = match lib.symbol("__rustc_codegen_backend") {
|
||||
Ok(f) => ::std::mem::transmute::<*mut u8, _>(f),
|
||||
Err(e) => sess.fatal(&format!("Couldnt load codegen backend as it\
|
||||
doesn't export the __rustc_backend_new symbol: {:?}", e)),
|
||||
};
|
||||
__rustc_codegen_backend(sess)
|
||||
};
|
||||
::std::mem::forget(lib);
|
||||
trans
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", backend_name, err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_trans(sess: &Session) -> Box<TransCrate> {
|
||||
let trans_name = sess.opts.debugging_opts.codegen_backend.clone();
|
||||
match trans_name.as_ref().map(|s|&**s) {
|
||||
None => DefaultTransCrate::new(&sess),
|
||||
Some("llvm") => rustc_trans::LlvmTransCrate::new(&sess),
|
||||
Some("metadata_only") => {
|
||||
rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new(&sess)
|
||||
}
|
||||
Some(filename) if filename.contains(".") => {
|
||||
load_backend_from_dylib(&sess, &filename)
|
||||
}
|
||||
Some(trans_name) => sess.fatal(&format!("Unknown codegen backend {}", trans_name)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,30 +271,36 @@ pub fn run_compiler<'a>(args: &[String],
|
||||
},
|
||||
};
|
||||
|
||||
let cstore = CStore::new(DefaultTransCrate::metadata_loader());
|
||||
|
||||
let loader = file_loader.unwrap_or(box RealFileLoader);
|
||||
let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
|
||||
let mut sess = session::build_session_with_codemap(
|
||||
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));
|
||||
|
||||
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;
|
||||
|
||||
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,
|
||||
&cstore,
|
||||
&input,
|
||||
&odir,
|
||||
&ofile), Some(sess));
|
||||
|
||||
let plugins = sess.opts.debugging_opts.extra_plugins.clone();
|
||||
let control = callbacks.build_controller(&sess, &matches);
|
||||
(driver::compile_input(&sess,
|
||||
|
||||
(driver::compile_input(trans,
|
||||
&sess,
|
||||
&cstore,
|
||||
&input_file_path,
|
||||
&input,
|
||||
@ -338,6 +393,7 @@ pub trait CompilerCalls<'a> {
|
||||
// be called just before actual compilation starts (and before build_controller
|
||||
// is called), after all arguments etc. have been completely handled.
|
||||
fn late_callback(&mut self,
|
||||
_: &TransCrate,
|
||||
_: &getopts::Matches,
|
||||
_: &Session,
|
||||
_: &CrateStore,
|
||||
@ -517,13 +573,18 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
||||
let mut sess = build_session(sopts.clone(),
|
||||
None,
|
||||
descriptions.clone());
|
||||
rustc_trans::init(&sess);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
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;
|
||||
let should_stop =
|
||||
RustcDefaultCalls::print_crate_info(&sess, None, odir, ofile);
|
||||
let should_stop = RustcDefaultCalls::print_crate_info(
|
||||
&*trans,
|
||||
&sess,
|
||||
None,
|
||||
odir,
|
||||
ofile
|
||||
);
|
||||
|
||||
if should_stop == Compilation::Stop {
|
||||
return None;
|
||||
@ -536,6 +597,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
||||
}
|
||||
|
||||
fn late_callback(&mut self,
|
||||
trans: &TransCrate,
|
||||
matches: &getopts::Matches,
|
||||
sess: &Session,
|
||||
cstore: &CrateStore,
|
||||
@ -543,7 +605,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
||||
odir: &Option<PathBuf>,
|
||||
ofile: &Option<PathBuf>)
|
||||
-> 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))
|
||||
}
|
||||
|
||||
@ -607,11 +669,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
||||
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) {
|
||||
enable_save_analysis(&mut control);
|
||||
}
|
||||
@ -681,11 +738,13 @@ impl RustcDefaultCalls {
|
||||
}
|
||||
|
||||
|
||||
fn print_crate_info(sess: &Session,
|
||||
fn print_crate_info(trans: &TransCrate,
|
||||
sess: &Session,
|
||||
input: Option<&Input>,
|
||||
odir: &Option<PathBuf>,
|
||||
ofile: &Option<PathBuf>)
|
||||
-> Compilation {
|
||||
use rustc::session::config::PrintRequest::*;
|
||||
// PrintRequest::NativeStaticLibs is special - printed during linking
|
||||
// (empty iterator returns true)
|
||||
if sess.opts.prints.iter().all(|&p| p==PrintRequest::NativeStaticLibs) {
|
||||
@ -707,15 +766,14 @@ impl RustcDefaultCalls {
|
||||
};
|
||||
for req in &sess.opts.prints {
|
||||
match *req {
|
||||
PrintRequest::TargetList => {
|
||||
TargetList => {
|
||||
let mut targets = rustc_back::target::get_targets().collect::<Vec<String>>();
|
||||
targets.sort();
|
||||
println!("{}", targets.join("\n"));
|
||||
},
|
||||
PrintRequest::Sysroot => println!("{}", sess.sysroot().display()),
|
||||
PrintRequest::TargetSpec => println!("{}", sess.target.target.to_json().pretty()),
|
||||
PrintRequest::FileNames |
|
||||
PrintRequest::CrateName => {
|
||||
Sysroot => println!("{}", sess.sysroot().display()),
|
||||
TargetSpec => println!("{}", sess.target.target.to_json().pretty()),
|
||||
FileNames | CrateName => {
|
||||
let input = match input {
|
||||
Some(input) => input,
|
||||
None => early_error(ErrorOutputType::default(), "no input file provided"),
|
||||
@ -741,7 +799,7 @@ impl RustcDefaultCalls {
|
||||
.to_string_lossy());
|
||||
}
|
||||
}
|
||||
PrintRequest::Cfg => {
|
||||
Cfg => {
|
||||
let allow_unstable_cfg = UnstableFeatures::from_environment()
|
||||
.is_nightly_build();
|
||||
|
||||
@ -781,29 +839,8 @@ impl RustcDefaultCalls {
|
||||
println!("{}", cfg);
|
||||
}
|
||||
}
|
||||
PrintRequest::RelocationModels => {
|
||||
println!("Available relocation models:");
|
||||
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);
|
||||
RelocationModels | CodeModels | TlsModels | TargetCPUs | TargetFeatures => {
|
||||
trans.print(*req, sess);
|
||||
}
|
||||
// Any output here interferes with Cargo's parsing of other printed output
|
||||
PrintRequest::NativeStaticLibs => {}
|
||||
@ -1281,6 +1318,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
|
||||
all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
|
||||
#[cfg(feature="llvm")]
|
||||
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_metadata::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_passes::DIAGNOSTICS);
|
||||
|
@ -228,7 +228,8 @@ impl PpSourceMode {
|
||||
}
|
||||
PpmTyped => {
|
||||
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,
|
||||
cstore,
|
||||
hir_map.clone(),
|
||||
@ -1080,7 +1081,8 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
|
||||
let mut out = Vec::new();
|
||||
|
||||
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,
|
||||
cstore,
|
||||
hir_map.clone(),
|
||||
|
@ -1,31 +0,0 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
use syntax::ast;
|
||||
use rustc::session::Session;
|
||||
use syntax::symbol::Symbol;
|
||||
use rustc_trans;
|
||||
|
||||
/// 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) {
|
||||
let tf = Symbol::intern("target_feature");
|
||||
|
||||
for feat in rustc_trans::target_features(sess) {
|
||||
cfg.insert((tf, Some(feat)));
|
||||
}
|
||||
|
||||
if sess.crt_static_feature() {
|
||||
cfg.insert((tf, Some(Symbol::intern("crt-static"))));
|
||||
}
|
||||
}
|
@ -16,7 +16,6 @@ use std::sync::mpsc;
|
||||
use driver;
|
||||
use rustc_lint;
|
||||
use rustc_resolve::MakeGlobMap;
|
||||
use rustc_trans;
|
||||
use rustc::middle::region;
|
||||
use rustc::ty::subst::{Kind, Subst};
|
||||
use rustc::traits::{ObligationCause, Reveal};
|
||||
@ -29,7 +28,6 @@ use rustc_metadata::cstore::CStore;
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::session::{self, config};
|
||||
use rustc::session::config::{OutputFilenames, OutputTypes};
|
||||
use rustc_trans_utils::trans_crate::TransCrate;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use syntax::abi::Abi;
|
||||
@ -104,12 +102,11 @@ fn test_env<F>(source_string: &str,
|
||||
options.unstable_features = UnstableFeatures::Allow;
|
||||
let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter);
|
||||
|
||||
let cstore = Rc::new(CStore::new(::DefaultTransCrate::metadata_loader()));
|
||||
let sess = session::build_session_(options,
|
||||
None,
|
||||
diagnostic_handler,
|
||||
Rc::new(CodeMap::new(FilePathMapping::empty())));
|
||||
rustc_trans::init(&sess);
|
||||
let cstore = Rc::new(CStore::new(::get_trans(&sess).metadata_loader()));
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
let input = config::Input::Str {
|
||||
name: FileName::Anon,
|
||||
|
@ -40,7 +40,7 @@ const CFG: &'static str = "cfg";
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
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(|| {
|
||||
if tcx.sess.opts.incremental.is_none() {
|
||||
return;
|
@ -32,6 +32,7 @@ extern crate syntax;
|
||||
extern crate syntax_pos;
|
||||
|
||||
mod assert_dep_graph;
|
||||
pub mod assert_module_sources;
|
||||
mod persist;
|
||||
|
||||
pub use assert_dep_graph::assert_dep_graph;
|
||||
|
@ -24,4 +24,3 @@ syntax = { path = "../libsyntax" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
byteorder = { version = "1.1", features = ["i128"] }
|
||||
rustc_apfloat = { path = "../librustc_apfloat" }
|
||||
rustc_trans_utils = { path = "../librustc_trans_utils" }
|
||||
|
@ -57,7 +57,6 @@ extern crate core; // for NonZero
|
||||
extern crate log_settings;
|
||||
extern crate rustc_apfloat;
|
||||
extern crate byteorder;
|
||||
extern crate rustc_trans_utils;
|
||||
|
||||
mod diagnostics;
|
||||
|
||||
|
@ -26,6 +26,7 @@ use std::fmt::{self, Write};
|
||||
use std::iter;
|
||||
use rustc::mir::mono::Linkage;
|
||||
use syntax_pos::symbol::Symbol;
|
||||
use syntax::codemap::Span;
|
||||
pub use rustc::mir::mono::MonoItem;
|
||||
|
||||
pub fn linkage_by_name(name: &str) -> Option<Linkage> {
|
||||
@ -244,6 +245,18 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
|
||||
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> {
|
||||
|
@ -22,6 +22,54 @@ pub mod collector;
|
||||
pub mod item;
|
||||
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>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
closure_did: DefId,
|
||||
|
@ -19,7 +19,7 @@ use rustc_allocator::{ALLOCATOR_METHODS, AllocatorTy};
|
||||
use ModuleLlvm;
|
||||
use llvm::{self, False, True};
|
||||
|
||||
pub unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) {
|
||||
pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) {
|
||||
let llcx = mods.llcx;
|
||||
let llmod = mods.llmod;
|
||||
let usize = match &tcx.sess.target.target.target_pointer_width[..] {
|
||||
|
@ -14,7 +14,7 @@
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::process::{self, Output, Child};
|
||||
use std::process::{self, Output};
|
||||
|
||||
pub struct Command {
|
||||
program: OsString,
|
||||
@ -81,10 +81,6 @@ impl Command {
|
||||
self.command().output()
|
||||
}
|
||||
|
||||
pub fn spawn(&mut self) -> io::Result<Child> {
|
||||
self.command().spawn()
|
||||
}
|
||||
|
||||
pub fn command(&self) -> process::Command {
|
||||
let mut ret = process::Command::new(&self.program);
|
||||
ret.args(&self.args);
|
||||
|
@ -141,10 +141,10 @@ pub fn remove(sess: &Session, path: &Path) {
|
||||
|
||||
/// Perform the linkage portion of the compilation phase. This will generate all
|
||||
/// of the requested outputs for this compilation session.
|
||||
pub fn link_binary(sess: &Session,
|
||||
trans: &CrateTranslation,
|
||||
outputs: &OutputFilenames,
|
||||
crate_name: &str) -> Vec<PathBuf> {
|
||||
pub(crate) fn link_binary(sess: &Session,
|
||||
trans: &CrateTranslation,
|
||||
outputs: &OutputFilenames,
|
||||
crate_name: &str) -> Vec<PathBuf> {
|
||||
let mut out_filenames = Vec::new();
|
||||
for &crate_type in sess.crate_types.borrow().iter() {
|
||||
// Ignore executable crates if we have -Z no-trans, as they will error.
|
||||
@ -201,9 +201,9 @@ fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilen
|
||||
out_filename
|
||||
}
|
||||
|
||||
pub fn each_linked_rlib(sess: &Session,
|
||||
info: &CrateInfo,
|
||||
f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> {
|
||||
pub(crate) fn each_linked_rlib(sess: &Session,
|
||||
info: &CrateInfo,
|
||||
f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> {
|
||||
let crates = info.used_crates_static.iter();
|
||||
let fmts = sess.dependency_formats.borrow();
|
||||
let fmts = fmts.get(&config::CrateTypeExecutable)
|
||||
@ -247,7 +247,7 @@ pub fn each_linked_rlib(sess: &Session,
|
||||
/// It's unusual for a crate to not participate in LTO. Typically only
|
||||
/// compiler-specific and unstable crates have a reason to not participate in
|
||||
/// LTO.
|
||||
pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool {
|
||||
pub(crate) fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool {
|
||||
// If our target enables builtin function lowering in LLVM then the
|
||||
// crates providing these functions don't participate in LTO (e.g.
|
||||
// no_builtins or compiler builtins crates).
|
||||
|
@ -42,7 +42,7 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum LtoModuleTranslation {
|
||||
pub(crate) enum LtoModuleTranslation {
|
||||
Fat {
|
||||
module: Option<ModuleTranslation>,
|
||||
_serialized_bitcode: Vec<SerializedModule>,
|
||||
@ -65,9 +65,9 @@ impl LtoModuleTranslation {
|
||||
/// points to LLVM data structures owned by this `LtoModuleTranslation`.
|
||||
/// It's intended that the module returned is immediately code generated and
|
||||
/// dropped, and then this LTO module is dropped.
|
||||
pub unsafe fn optimize(&mut self,
|
||||
cgcx: &CodegenContext,
|
||||
timeline: &mut Timeline)
|
||||
pub(crate) unsafe fn optimize(&mut self,
|
||||
cgcx: &CodegenContext,
|
||||
timeline: &mut Timeline)
|
||||
-> Result<ModuleTranslation, FatalError>
|
||||
{
|
||||
match *self {
|
||||
@ -100,7 +100,7 @@ pub enum LTOMode {
|
||||
JustThisCrate,
|
||||
}
|
||||
|
||||
pub fn run(cgcx: &CodegenContext,
|
||||
pub(crate) fn run(cgcx: &CodegenContext,
|
||||
modules: Vec<ModuleTranslation>,
|
||||
mode: LTOMode,
|
||||
timeline: &mut Timeline)
|
||||
|
@ -363,7 +363,7 @@ impl CodegenContext {
|
||||
Handler::with_emitter(true, false, Box::new(self.diag_emitter.clone()))
|
||||
}
|
||||
|
||||
pub fn config(&self, kind: ModuleKind) -> &ModuleConfig {
|
||||
pub(crate) fn config(&self, kind: ModuleKind) -> &ModuleConfig {
|
||||
match kind {
|
||||
ModuleKind::Regular => &self.regular_module_config,
|
||||
ModuleKind::Metadata => &self.metadata_module_config,
|
||||
@ -371,7 +371,7 @@ impl CodegenContext {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_temp_bitcode(&self, trans: &ModuleTranslation, name: &str) {
|
||||
pub(crate) fn save_temp_bitcode(&self, trans: &ModuleTranslation, name: &str) {
|
||||
if !self.save_temps {
|
||||
return
|
||||
}
|
||||
@ -822,7 +822,7 @@ fn binaryen_assemble(cgcx: &CodegenContext,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CompiledModules {
|
||||
pub(crate) struct CompiledModules {
|
||||
pub modules: Vec<CompiledModule>,
|
||||
pub metadata_module: CompiledModule,
|
||||
pub allocator_module: Option<CompiledModule>,
|
||||
@ -1162,7 +1162,7 @@ fn produce_final_output_artifacts(sess: &Session,
|
||||
// These are used in linking steps and will be cleaned up afterward.
|
||||
}
|
||||
|
||||
pub fn dump_incremental_data(trans: &CrateTranslation) {
|
||||
pub(crate) fn dump_incremental_data(trans: &CrateTranslation) {
|
||||
println!("[incremental] Re-using {} out of {} modules",
|
||||
trans.modules.iter().filter(|m| m.pre_existing).count(),
|
||||
trans.modules.len());
|
||||
@ -2144,7 +2144,7 @@ pub struct OngoingCrateTranslation {
|
||||
}
|
||||
|
||||
impl OngoingCrateTranslation {
|
||||
pub fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslation {
|
||||
pub(crate) fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslation {
|
||||
self.shared_emitter_main.check(sess, true);
|
||||
let compiled_modules = match self.future.join() {
|
||||
Ok(Ok(compiled_modules)) => compiled_modules,
|
||||
@ -2212,9 +2212,9 @@ impl OngoingCrateTranslation {
|
||||
trans
|
||||
}
|
||||
|
||||
pub fn submit_pre_translated_module_to_llvm(&self,
|
||||
tcx: TyCtxt,
|
||||
mtrans: ModuleTranslation) {
|
||||
pub(crate) fn submit_pre_translated_module_to_llvm(&self,
|
||||
tcx: TyCtxt,
|
||||
mtrans: ModuleTranslation) {
|
||||
self.wait_for_signal_to_translate_item();
|
||||
self.check_for_errors(tcx.sess);
|
||||
|
||||
@ -2247,9 +2247,9 @@ impl OngoingCrateTranslation {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn submit_translated_module_to_llvm(tcx: TyCtxt,
|
||||
mtrans: ModuleTranslation,
|
||||
cost: u64) {
|
||||
pub(crate) fn submit_translated_module_to_llvm(tcx: TyCtxt,
|
||||
mtrans: ModuleTranslation,
|
||||
cost: u64) {
|
||||
let llvm_work_item = WorkItem::Optimize(mtrans);
|
||||
drop(tcx.tx_to_llvm_workers.send(Box::new(Message::TranslationDone {
|
||||
llvm_work_item,
|
||||
|
@ -29,7 +29,6 @@ use super::ModuleTranslation;
|
||||
use super::ModuleKind;
|
||||
|
||||
use abi;
|
||||
use assert_module_sources;
|
||||
use back::link;
|
||||
use back::symbol_export;
|
||||
use back::write::{self, OngoingCrateTranslation, create_target_machine};
|
||||
@ -66,7 +65,7 @@ use meth;
|
||||
use mir;
|
||||
use monomorphize::Instance;
|
||||
use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
|
||||
use symbol_names_test;
|
||||
use rustc_trans_utils::symbol_names_test;
|
||||
use time_graph;
|
||||
use trans_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames};
|
||||
use type_::Type;
|
||||
@ -904,7 +903,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
total_trans_time);
|
||||
|
||||
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);
|
||||
@ -947,54 +946,6 @@ fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, '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>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cnum: CrateNum,
|
||||
@ -1034,7 +985,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
|
||||
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() {
|
||||
PartitioningStrategy::PerModule
|
||||
|
@ -47,27 +47,9 @@ unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok!
|
||||
```
|
||||
"##,
|
||||
|
||||
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 @@
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(conservative_impl_trait)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
|
||||
use rustc::dep_graph::WorkProduct;
|
||||
use syntax_pos::symbol::Symbol;
|
||||
@ -66,11 +67,9 @@ extern crate serialize;
|
||||
extern crate cc; // Used to locate MSVC
|
||||
extern crate tempdir;
|
||||
|
||||
pub use base::trans_crate;
|
||||
use back::bytecode::RLIB_BYTECODE_EXTENSION;
|
||||
|
||||
pub use metadata::LlvmMetadataLoader;
|
||||
pub use llvm_util::{init, target_features, print_version, print_passes, print};
|
||||
pub use llvm_util::{target_features, print_version, print_passes};
|
||||
|
||||
use std::any::Any;
|
||||
use std::path::PathBuf;
|
||||
@ -81,24 +80,24 @@ use rustc::dep_graph::DepGraph;
|
||||
use rustc::hir::def_id::CrateNum;
|
||||
use rustc::middle::cstore::MetadataLoader;
|
||||
use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource};
|
||||
use rustc::session::Session;
|
||||
use rustc::session::config::{OutputFilenames, OutputType};
|
||||
use rustc::session::{Session, CompileIncomplete};
|
||||
use rustc::session::config::{OutputFilenames, OutputType, PrintRequest};
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::util::nodemap::{FxHashSet, FxHashMap};
|
||||
|
||||
use rustc_mir::monomorphize;
|
||||
use rustc_trans_utils::trans_crate::TransCrate;
|
||||
|
||||
mod diagnostics;
|
||||
|
||||
pub mod back {
|
||||
mod back {
|
||||
pub use rustc_trans_utils::symbol_names;
|
||||
mod archive;
|
||||
pub mod bytecode;
|
||||
mod command;
|
||||
pub(crate) mod linker;
|
||||
pub mod linker;
|
||||
pub mod link;
|
||||
mod lto;
|
||||
pub(crate) mod symbol_export;
|
||||
pub(crate) mod symbol_names;
|
||||
pub mod symbol_export;
|
||||
pub mod write;
|
||||
mod rpath;
|
||||
}
|
||||
@ -106,7 +105,6 @@ pub mod back {
|
||||
mod abi;
|
||||
mod allocator;
|
||||
mod asm;
|
||||
mod assert_module_sources;
|
||||
mod attributes;
|
||||
mod base;
|
||||
mod builder;
|
||||
@ -139,7 +137,6 @@ mod llvm_util;
|
||||
mod metadata;
|
||||
mod meth;
|
||||
mod mir;
|
||||
mod symbol_names_test;
|
||||
mod time_graph;
|
||||
mod trans_item;
|
||||
mod type_;
|
||||
@ -148,57 +145,118 @@ mod value;
|
||||
|
||||
pub struct LlvmTransCrate(());
|
||||
|
||||
impl !Send for LlvmTransCrate {} // Llvm is on a per-thread basis
|
||||
impl !Sync for LlvmTransCrate {}
|
||||
|
||||
impl LlvmTransCrate {
|
||||
pub fn new() -> Self {
|
||||
LlvmTransCrate(())
|
||||
pub fn new(sess: &Session) -> Box<TransCrate> {
|
||||
llvm_util::init(sess); // Make sure llvm is inited
|
||||
box LlvmTransCrate(())
|
||||
}
|
||||
}
|
||||
|
||||
impl rustc_trans_utils::trans_crate::TransCrate for LlvmTransCrate {
|
||||
type MetadataLoader = metadata::LlvmMetadataLoader;
|
||||
type OngoingCrateTranslation = back::write::OngoingCrateTranslation;
|
||||
type TranslatedCrate = CrateTranslation;
|
||||
impl TransCrate for LlvmTransCrate {
|
||||
fn print(&self, req: PrintRequest, sess: &Session) {
|
||||
match req {
|
||||
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 metadata_loader() -> Box<MetadataLoader> {
|
||||
fn target_features(&self, sess: &Session) -> Vec<Symbol> {
|
||||
target_features(sess)
|
||||
}
|
||||
|
||||
fn metadata_loader(&self) -> Box<MetadataLoader> {
|
||||
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_export::provide(providers);
|
||||
base::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);
|
||||
}
|
||||
|
||||
fn trans_crate<'a, 'tcx>(
|
||||
&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
rx: mpsc::Receiver<Box<Any + Send>>
|
||||
) -> Self::OngoingCrateTranslation {
|
||||
base::trans_crate(tcx, rx)
|
||||
) -> Box<Any> {
|
||||
box base::trans_crate(tcx, rx)
|
||||
}
|
||||
|
||||
fn join_trans(
|
||||
trans: Self::OngoingCrateTranslation,
|
||||
fn join_trans_and_link(
|
||||
&self,
|
||||
trans: Box<Any>,
|
||||
sess: &Session,
|
||||
dep_graph: &DepGraph
|
||||
) -> Self::TranslatedCrate {
|
||||
trans.join(sess, dep_graph)
|
||||
}
|
||||
dep_graph: &DepGraph,
|
||||
outputs: &OutputFilenames,
|
||||
) -> 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) {
|
||||
back::link::link_binary(sess, trans, outputs, &trans.crate_name.as_str());
|
||||
}
|
||||
time(sess.time_passes(),
|
||||
"serialize work products",
|
||||
move || rustc_incremental::save_work_products(sess, &dep_graph));
|
||||
|
||||
fn dump_incremental_data(trans: &Self::TranslatedCrate) {
|
||||
back::write::dump_incremental_data(trans);
|
||||
sess.compile_status()?;
|
||||
|
||||
if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
|
||||
i == OutputType::Metadata) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// 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", || {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ModuleTranslation {
|
||||
/// This is the entrypoint for a hot plugged rustc_trans
|
||||
#[no_mangle]
|
||||
pub fn __rustc_codegen_backend(sess: &Session) -> Box<TransCrate> {
|
||||
LlvmTransCrate::new(sess)
|
||||
}
|
||||
|
||||
struct ModuleTranslation {
|
||||
/// The name of the module. When the crate may be saved between
|
||||
/// compilations, incremental compilation requires that name be
|
||||
/// unique amongst **all** crates. Therefore, it should contain
|
||||
@ -206,26 +264,26 @@ pub struct ModuleTranslation {
|
||||
/// as the crate name and disambiguator.
|
||||
name: String,
|
||||
llmod_id: String,
|
||||
pub source: ModuleSource,
|
||||
pub kind: ModuleKind,
|
||||
source: ModuleSource,
|
||||
kind: ModuleKind,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum ModuleKind {
|
||||
enum ModuleKind {
|
||||
Regular,
|
||||
Metadata,
|
||||
Allocator,
|
||||
}
|
||||
|
||||
impl ModuleTranslation {
|
||||
pub fn llvm(&self) -> Option<&ModuleLlvm> {
|
||||
fn llvm(&self) -> Option<&ModuleLlvm> {
|
||||
match self.source {
|
||||
ModuleSource::Translated(ref llvm) => Some(llvm),
|
||||
ModuleSource::Preexisting(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_compiled_module(self,
|
||||
fn into_compiled_module(self,
|
||||
emit_obj: bool,
|
||||
emit_bc: bool,
|
||||
emit_bc_compressed: bool,
|
||||
@ -264,17 +322,17 @@ impl ModuleTranslation {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CompiledModule {
|
||||
pub name: String,
|
||||
pub llmod_id: String,
|
||||
pub kind: ModuleKind,
|
||||
pub pre_existing: bool,
|
||||
pub object: Option<PathBuf>,
|
||||
pub bytecode: Option<PathBuf>,
|
||||
pub bytecode_compressed: Option<PathBuf>,
|
||||
struct CompiledModule {
|
||||
name: String,
|
||||
llmod_id: String,
|
||||
kind: ModuleKind,
|
||||
pre_existing: bool,
|
||||
object: Option<PathBuf>,
|
||||
bytecode: Option<PathBuf>,
|
||||
bytecode_compressed: Option<PathBuf>,
|
||||
}
|
||||
|
||||
pub enum ModuleSource {
|
||||
enum ModuleSource {
|
||||
/// Copy the `.o` files or whatever from the incr. comp. directory.
|
||||
Preexisting(WorkProduct),
|
||||
|
||||
@ -283,9 +341,9 @@ pub enum ModuleSource {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ModuleLlvm {
|
||||
struct ModuleLlvm {
|
||||
llcx: llvm::ContextRef,
|
||||
pub llmod: llvm::ModuleRef,
|
||||
llmod: llvm::ModuleRef,
|
||||
tm: llvm::TargetMachineRef,
|
||||
}
|
||||
|
||||
@ -302,20 +360,20 @@ impl Drop for ModuleLlvm {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CrateTranslation {
|
||||
pub crate_name: Symbol,
|
||||
pub modules: Vec<CompiledModule>,
|
||||
struct CrateTranslation {
|
||||
crate_name: Symbol,
|
||||
modules: Vec<CompiledModule>,
|
||||
allocator_module: Option<CompiledModule>,
|
||||
metadata_module: CompiledModule,
|
||||
pub link: rustc::middle::cstore::LinkMeta,
|
||||
pub metadata: rustc::middle::cstore::EncodedMetadata,
|
||||
link: rustc::middle::cstore::LinkMeta,
|
||||
metadata: rustc::middle::cstore::EncodedMetadata,
|
||||
windows_subsystem: Option<String>,
|
||||
linker_info: back::linker::LinkerInfo,
|
||||
crate_info: CrateInfo,
|
||||
}
|
||||
|
||||
// Misc info we load from metadata to persist beyond the tcx
|
||||
pub struct CrateInfo {
|
||||
struct CrateInfo {
|
||||
panic_runtime: Option<CrateNum>,
|
||||
compiler_builtins: Option<CrateNum>,
|
||||
profiler_runtime: Option<CrateNum>,
|
||||
|
@ -19,11 +19,12 @@ use std::ffi::{CStr, CString};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
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 {
|
||||
// Before we touch LLVM, make sure that multithreading is enabled.
|
||||
static POISONED: AtomicBool = AtomicBool::new(false);
|
||||
static INIT: Once = Once::new();
|
||||
INIT.call_once(|| {
|
||||
if llvm::LLVMStartMultithreaded() != 1 {
|
||||
// use an extra bool to make sure that all future usage of LLVM
|
||||
@ -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) {
|
||||
let mut llvm_c_strs = Vec::new();
|
||||
let mut llvm_args = Vec::new();
|
||||
@ -125,6 +133,7 @@ pub fn target_feature_whitelist(sess: &Session) -> Vec<&CStr> {
|
||||
}
|
||||
|
||||
pub fn print_version() {
|
||||
// Can be called without initializing LLVM
|
||||
unsafe {
|
||||
println!("LLVM version: {}.{}",
|
||||
llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
|
||||
@ -132,10 +141,12 @@ pub fn print_version() {
|
||||
}
|
||||
|
||||
pub fn print_passes() {
|
||||
// Can be called without initializing LLVM
|
||||
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);
|
||||
unsafe {
|
||||
match req {
|
||||
|
@ -25,11 +25,10 @@ use monomorphize::Instance;
|
||||
use type_of::LayoutLlvmExt;
|
||||
use rustc::hir;
|
||||
use rustc::mir::mono::{Linkage, Visibility};
|
||||
use rustc::ty::{TyCtxt, TypeFoldable};
|
||||
use rustc::ty::TypeFoldable;
|
||||
use rustc::ty::layout::LayoutOf;
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax_pos::Span;
|
||||
use std::fmt;
|
||||
|
||||
pub use rustc::mir::mono::MonoItem;
|
||||
@ -107,18 +106,6 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
|
||||
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 {
|
||||
match *self.as_mono_item() {
|
||||
MonoItem::Fn(instance) => {
|
||||
|
@ -19,3 +19,5 @@ syntax_pos = { path = "../libsyntax_pos" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_mir = { path = "../librustc_mir" }
|
||||
rustc_incremental = { path = "../librustc_incremental" }
|
||||
|
38
src/librustc_trans_utils/diagnostics.rs
Normal file
38
src/librustc_trans_utils/diagnostics.rs
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
register_long_diagnostics! {
|
||||
|
||||
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() {}
|
||||
```
|
||||
"##,
|
||||
|
||||
}
|
@ -35,18 +35,26 @@ extern crate log;
|
||||
#[macro_use]
|
||||
extern crate rustc;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_mir;
|
||||
extern crate rustc_incremental;
|
||||
#[macro_use]
|
||||
extern crate syntax;
|
||||
extern crate syntax_pos;
|
||||
extern crate rustc_data_structures;
|
||||
|
||||
pub extern crate rustc as __rustc;
|
||||
|
||||
use rustc::ty::{TyCtxt, Instance};
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::LOCAL_CRATE;
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::util::nodemap::NodeSet;
|
||||
|
||||
pub mod diagnostics;
|
||||
pub mod link;
|
||||
pub mod trans_crate;
|
||||
pub mod symbol_names;
|
||||
pub mod symbol_names_test;
|
||||
|
||||
/// check for the #[rustc_error] annotation, which forces an
|
||||
/// error in trans. This is used to write compile-fail tests
|
||||
@ -110,3 +118,6 @@ pub fn find_exported_symbols<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet {
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))] // remove after the next snapshot
|
||||
__build_diagnostic_array! { librustc_trans_utils, DIAGNOSTICS }
|
||||
|
@ -97,11 +97,9 @@
|
||||
//! virtually impossible. Thus, symbol hash generation exclusively relies on
|
||||
//! 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::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::map as hir_map;
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
@ -19,7 +19,7 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::ty::TyCtxt;
|
||||
use syntax::ast;
|
||||
|
||||
use monomorphize::Instance;
|
||||
use rustc_mir::monomorphize::Instance;
|
||||
|
||||
const SYMBOL_NAME: &'static str = "rustc_symbol_name";
|
||||
const ITEM_PATH: &'static str = "rustc_item_path";
|
@ -26,6 +26,7 @@ use std::io::prelude::*;
|
||||
use std::io::{self, Cursor};
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
use std::sync::mpsc;
|
||||
|
||||
use rustc_data_structures::owning_ref::{ErasedBoxRef, OwningRef};
|
||||
@ -35,83 +36,81 @@ use flate2::write::DeflateEncoder;
|
||||
|
||||
use syntax::symbol::Symbol;
|
||||
use rustc::hir::def_id::LOCAL_CRATE;
|
||||
use rustc::session::Session;
|
||||
use rustc::session::config::{CrateType, OutputFilenames};
|
||||
use rustc::session::{Session, CompileIncomplete};
|
||||
use rustc::session::config::{CrateType, OutputFilenames, PrintRequest};
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::middle::cstore::EncodedMetadata;
|
||||
use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait;
|
||||
use rustc::middle::cstore::MetadataLoader;
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc_back::target::Target;
|
||||
use rustc_mir::monomorphize::collector;
|
||||
use link::{build_link_meta, out_filename};
|
||||
|
||||
pub trait TransCrate {
|
||||
type MetadataLoader: MetadataLoaderTrait;
|
||||
type OngoingCrateTranslation;
|
||||
type TranslatedCrate;
|
||||
fn print(&self, _req: PrintRequest, _sess: &Session) {}
|
||||
fn target_features(&self, _sess: &Session) -> Vec<Symbol> { vec![] }
|
||||
|
||||
fn metadata_loader() -> Box<MetadataLoaderTrait>;
|
||||
fn provide(_providers: &mut Providers);
|
||||
fn provide_extern(_providers: &mut Providers);
|
||||
fn metadata_loader(&self) -> Box<MetadataLoader>;
|
||||
fn provide(&self, _providers: &mut Providers);
|
||||
fn provide_extern(&self, _providers: &mut Providers);
|
||||
fn trans_crate<'a, 'tcx>(
|
||||
&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
rx: mpsc::Receiver<Box<Any + Send>>
|
||||
) -> Self::OngoingCrateTranslation;
|
||||
fn join_trans(
|
||||
trans: Self::OngoingCrateTranslation,
|
||||
) -> Box<Any>;
|
||||
|
||||
/// 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,
|
||||
dep_graph: &DepGraph
|
||||
) -> Self::TranslatedCrate;
|
||||
fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames);
|
||||
fn dump_incremental_data(trans: &Self::TranslatedCrate);
|
||||
dep_graph: &DepGraph,
|
||||
outputs: &OutputFilenames,
|
||||
) -> Result<(), CompileIncomplete>;
|
||||
}
|
||||
|
||||
pub struct DummyTransCrate;
|
||||
|
||||
impl TransCrate for DummyTransCrate {
|
||||
type MetadataLoader = DummyMetadataLoader;
|
||||
type OngoingCrateTranslation = ();
|
||||
type TranslatedCrate = ();
|
||||
|
||||
fn metadata_loader() -> Box<MetadataLoaderTrait> {
|
||||
fn metadata_loader(&self) -> Box<MetadataLoader> {
|
||||
box DummyMetadataLoader(())
|
||||
}
|
||||
|
||||
fn provide(_providers: &mut Providers) {
|
||||
fn provide(&self, _providers: &mut Providers) {
|
||||
bug!("DummyTransCrate::provide");
|
||||
}
|
||||
|
||||
fn provide_extern(_providers: &mut Providers) {
|
||||
fn provide_extern(&self, _providers: &mut Providers) {
|
||||
bug!("DummyTransCrate::provide_extern");
|
||||
}
|
||||
|
||||
fn trans_crate<'a, 'tcx>(
|
||||
&self,
|
||||
_tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
_rx: mpsc::Receiver<Box<Any + Send>>
|
||||
) -> Self::OngoingCrateTranslation {
|
||||
) -> Box<Any> {
|
||||
bug!("DummyTransCrate::trans_crate");
|
||||
}
|
||||
|
||||
fn join_trans(
|
||||
_trans: Self::OngoingCrateTranslation,
|
||||
fn join_trans_and_link(
|
||||
&self,
|
||||
_trans: Box<Any>,
|
||||
_sess: &Session,
|
||||
_dep_graph: &DepGraph
|
||||
) -> Self::TranslatedCrate {
|
||||
bug!("DummyTransCrate::join_trans");
|
||||
}
|
||||
|
||||
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");
|
||||
_dep_graph: &DepGraph,
|
||||
_outputs: &OutputFilenames,
|
||||
) -> Result<(), CompileIncomplete> {
|
||||
bug!("DummyTransCrate::join_trans_and_link");
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DummyMetadataLoader(());
|
||||
|
||||
impl MetadataLoaderTrait for DummyMetadataLoader {
|
||||
impl MetadataLoader for DummyMetadataLoader {
|
||||
fn get_rlib_metadata(
|
||||
&self,
|
||||
_target: &Target,
|
||||
@ -131,7 +130,7 @@ impl MetadataLoaderTrait for DummyMetadataLoader {
|
||||
|
||||
pub struct NoLlvmMetadataLoader;
|
||||
|
||||
impl MetadataLoaderTrait for NoLlvmMetadataLoader {
|
||||
impl MetadataLoader for NoLlvmMetadataLoader {
|
||||
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
let file = File::open(filename)
|
||||
.map_err(|e| format!("metadata file open err: {:?}", e))?;
|
||||
@ -161,87 +160,132 @@ impl MetadataLoaderTrait for NoLlvmMetadataLoader {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MetadataOnlyTransCrate;
|
||||
pub struct MetadataOnlyTransCrate(());
|
||||
pub struct OngoingCrateTranslation {
|
||||
metadata: EncodedMetadata,
|
||||
metadata_version: Vec<u8>,
|
||||
crate_name: Symbol,
|
||||
}
|
||||
pub struct TranslatedCrate(OngoingCrateTranslation);
|
||||
|
||||
impl MetadataOnlyTransCrate {
|
||||
#[allow(dead_code)]
|
||||
pub fn new() -> Self {
|
||||
MetadataOnlyTransCrate
|
||||
pub fn new(sess: &Session) -> Box<TransCrate> {
|
||||
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)
|
||||
);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
box MetadataOnlyTransCrate(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TransCrate for MetadataOnlyTransCrate {
|
||||
type MetadataLoader = NoLlvmMetadataLoader;
|
||||
type OngoingCrateTranslation = OngoingCrateTranslation;
|
||||
type TranslatedCrate = TranslatedCrate;
|
||||
|
||||
fn metadata_loader() -> Box<MetadataLoaderTrait> {
|
||||
fn metadata_loader(&self) -> Box<MetadataLoader> {
|
||||
box NoLlvmMetadataLoader
|
||||
}
|
||||
|
||||
fn provide(_providers: &mut Providers) {}
|
||||
fn provide_extern(_providers: &mut Providers) {}
|
||||
fn provide(&self, providers: &mut Providers) {
|
||||
::symbol_names::provide(providers);
|
||||
providers.target_features_enabled = |_tcx, _id| {
|
||||
Rc::new(Vec::new()) // Just a dummy
|
||||
};
|
||||
}
|
||||
fn provide_extern(&self, _providers: &mut Providers) {}
|
||||
|
||||
fn trans_crate<'a, 'tcx>(
|
||||
&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
_rx: mpsc::Receiver<Box<Any + Send>>
|
||||
) -> Self::OngoingCrateTranslation {
|
||||
) -> Box<Any> {
|
||||
use rustc_mir::monomorphize::item::MonoItem;
|
||||
|
||||
::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.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();
|
||||
|
||||
let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE));
|
||||
let exported_symbols = ::find_exported_symbols(tcx);
|
||||
let metadata = tcx.encode_metadata(&link_meta, &exported_symbols);
|
||||
|
||||
OngoingCrateTranslation {
|
||||
box OngoingCrateTranslation {
|
||||
metadata: metadata,
|
||||
metadata_version: tcx.metadata_encoding_version().to_vec(),
|
||||
crate_name: tcx.crate_name(LOCAL_CRATE),
|
||||
}
|
||||
}
|
||||
|
||||
fn join_trans(
|
||||
trans: Self::OngoingCrateTranslation,
|
||||
_sess: &Session,
|
||||
fn join_trans_and_link(
|
||||
&self,
|
||||
trans: Box<Any>,
|
||||
sess: &Session,
|
||||
_dep_graph: &DepGraph,
|
||||
) -> Self::TranslatedCrate {
|
||||
TranslatedCrate(trans)
|
||||
}
|
||||
|
||||
fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) {
|
||||
outputs: &OutputFilenames,
|
||||
) -> Result<(), CompileIncomplete> {
|
||||
let trans = trans.downcast::<OngoingCrateTranslation>()
|
||||
.expect("Expected MetadataOnlyTransCrate's OngoingCrateTranslation, found Box<Any>");
|
||||
for &crate_type in sess.opts.crate_types.iter() {
|
||||
if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib {
|
||||
continue;
|
||||
}
|
||||
let output_name =
|
||||
out_filename(sess, crate_type, &outputs, &trans.0.crate_name.as_str());
|
||||
let mut compressed = trans.0.metadata_version.clone();
|
||||
out_filename(sess, crate_type, &outputs, &trans.crate_name.as_str());
|
||||
let mut compressed = trans.metadata_version.clone();
|
||||
let metadata = if crate_type == CrateType::CrateTypeDylib {
|
||||
DeflateEncoder::new(&mut compressed, Compression::fast())
|
||||
.write_all(&trans.0.metadata.raw_data)
|
||||
.write_all(&trans.metadata.raw_data)
|
||||
.unwrap();
|
||||
&compressed
|
||||
} else {
|
||||
&trans.0.metadata.raw_data
|
||||
&trans.metadata.raw_data
|
||||
};
|
||||
let mut builder = Builder::new(File::create(&output_name).unwrap());
|
||||
let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64);
|
||||
builder.append(&header, Cursor::new(metadata)).unwrap();
|
||||
}
|
||||
|
||||
sess.abort_if_errors();
|
||||
if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib)
|
||||
&& !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) {
|
||||
&& !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib)
|
||||
{
|
||||
sess.fatal("Executables are not supported by the metadata-only backend.");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dump_incremental_data(_trans: &Self::TranslatedCrate) {}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ use rustc::hir::map as hir_map;
|
||||
use rustc::lint;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_trans;
|
||||
use rustc_trans::back::link;
|
||||
use rustc_resolve as resolve;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
|
||||
@ -140,22 +139,22 @@ pub fn run_core(search_paths: SearchPaths,
|
||||
false,
|
||||
Some(codemap.clone()));
|
||||
|
||||
let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
|
||||
let mut sess = session::build_session_(
|
||||
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));
|
||||
|
||||
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;
|
||||
|
||||
let control = &driver::CompileController::basic();
|
||||
|
||||
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 result = driver::phase_2_configure_and_expand(&sess,
|
||||
@ -177,7 +176,8 @@ pub fn run_core(search_paths: SearchPaths,
|
||||
&[],
|
||||
&sess);
|
||||
|
||||
abort_on_err(driver::phase_3_run_analysis_passes(control,
|
||||
abort_on_err(driver::phase_3_run_analysis_passes(&*trans,
|
||||
control,
|
||||
&sess,
|
||||
&*cstore,
|
||||
hir_map,
|
||||
|
@ -34,7 +34,7 @@ extern crate libc;
|
||||
extern crate rustc;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_const_math;
|
||||
extern crate rustc_trans;
|
||||
extern crate rustc_trans_utils;
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_resolve;
|
||||
extern crate rustc_lint;
|
||||
@ -63,6 +63,8 @@ use std::path::{Path, PathBuf};
|
||||
use std::process;
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
use rustc_driver::rustc_trans;
|
||||
|
||||
use externalfiles::ExternalHtml;
|
||||
use rustc::session::search_paths::SearchPaths;
|
||||
use rustc::session::config::{ErrorOutputType, RustcOptGroup, nightly_options,
|
||||
|
@ -34,7 +34,6 @@ use rustc_driver::driver::phase_2_configure_and_expand;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
use rustc_resolve::MakeGlobMap;
|
||||
use rustc_trans;
|
||||
use rustc_trans::back::link;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::CodeMap;
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
@ -82,11 +81,11 @@ pub fn run(input_path: &Path,
|
||||
true, false,
|
||||
Some(codemap.clone()));
|
||||
|
||||
let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
|
||||
let mut sess = session::build_session_(
|
||||
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));
|
||||
sess.parse_sess.config =
|
||||
config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
|
||||
@ -108,7 +107,7 @@ pub fn run(input_path: &Path,
|
||||
};
|
||||
|
||||
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 mut collector = Collector::new(crate_name,
|
||||
@ -247,11 +246,11 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
|
||||
// Compile the code
|
||||
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_(
|
||||
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));
|
||||
|
||||
let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"));
|
||||
@ -266,7 +265,17 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
|
||||
}
|
||||
|
||||
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 {
|
||||
|
9
src/test/run-make/hotplug_codegen_backend/Makefile
Normal file
9
src/test/run-make/hotplug_codegen_backend/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
include ../tools.mk
|
||||
|
||||
all:
|
||||
/bin/echo || exit 0 # This test requires /bin/echo to exist
|
||||
$(RUSTC) the_backend.rs --crate-name the_backend --crate-type dylib \
|
||||
-o $(TMPDIR)/the_backend.dylib
|
||||
$(RUSTC) some_crate.rs --crate-name some_crate --crate-type bin -o $(TMPDIR)/some_crate \
|
||||
-Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options
|
||||
grep -x "This has been \"compiled\" succesfully." $(TMPDIR)/some_crate
|
13
src/test/run-make/hotplug_codegen_backend/some_crate.rs
Normal file
13
src/test/run-make/hotplug_codegen_backend/some_crate.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
fn main() {
|
||||
::std::process::exit(1);
|
||||
}
|
82
src/test/run-make/hotplug_codegen_backend/the_backend.rs
Normal file
82
src/test/run-make/hotplug_codegen_backend/the_backend.rs
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright 2017 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(rustc_private)]
|
||||
|
||||
extern crate syntax;
|
||||
extern crate rustc;
|
||||
extern crate rustc_trans_utils;
|
||||
|
||||
use std::any::Any;
|
||||
use std::sync::mpsc;
|
||||
use syntax::symbol::Symbol;
|
||||
use rustc::session::{Session, CompileIncomplete};
|
||||
use rustc::session::config::OutputFilenames;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::middle::cstore::MetadataLoader;
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc_trans_utils::trans_crate::{TransCrate, MetadataOnlyTransCrate};
|
||||
|
||||
struct TheBackend(Box<TransCrate>);
|
||||
|
||||
impl TransCrate for TheBackend {
|
||||
fn metadata_loader(&self) -> Box<MetadataLoader> {
|
||||
self.0.metadata_loader()
|
||||
}
|
||||
|
||||
fn provide(&self, providers: &mut Providers) {
|
||||
self.0.provide(providers);
|
||||
}
|
||||
|
||||
fn provide_extern(&self, providers: &mut Providers) {
|
||||
self.0.provide_extern(providers);
|
||||
}
|
||||
|
||||
fn trans_crate<'a, 'tcx>(
|
||||
&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
_rx: mpsc::Receiver<Box<Any + Send>>
|
||||
) -> Box<Any> {
|
||||
use rustc::hir::def_id::LOCAL_CRATE;
|
||||
|
||||
Box::new(tcx.crate_name(LOCAL_CRATE) as Symbol)
|
||||
}
|
||||
|
||||
fn join_trans_and_link(
|
||||
&self,
|
||||
trans: Box<Any>,
|
||||
sess: &Session,
|
||||
_dep_graph: &DepGraph,
|
||||
outputs: &OutputFilenames,
|
||||
) -> Result<(), CompileIncomplete> {
|
||||
use std::io::Write;
|
||||
use rustc::session::config::CrateType;
|
||||
use rustc_trans_utils::link::out_filename;
|
||||
let crate_name = trans.downcast::<Symbol>()
|
||||
.expect("in join_trans_and_link: trans is not a Symbol");
|
||||
for &crate_type in sess.opts.crate_types.iter() {
|
||||
if crate_type != CrateType::CrateTypeExecutable {
|
||||
sess.fatal(&format!("Crate type is {:?}", crate_type));
|
||||
}
|
||||
let output_name =
|
||||
out_filename(sess, crate_type, &outputs, &*crate_name.as_str());
|
||||
let mut out_file = ::std::fs::File::create(output_name).unwrap();
|
||||
write!(out_file, "This has been \"compiled\" succesfully.").unwrap();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// This is the entrypoint for a hot plugged rustc_trans
|
||||
#[no_mangle]
|
||||
pub fn __rustc_codegen_backend(sess: &Session) -> Box<TransCrate> {
|
||||
Box::new(TheBackend(MetadataOnlyTransCrate::new(sess)))
|
||||
}
|
@ -16,6 +16,7 @@ extern crate rustc_lint;
|
||||
extern crate rustc_metadata;
|
||||
extern crate rustc_errors;
|
||||
extern crate rustc_trans;
|
||||
extern crate rustc_trans_utils;
|
||||
extern crate syntax;
|
||||
|
||||
use rustc::session::{build_session, Session};
|
||||
@ -25,6 +26,7 @@ use rustc_driver::driver::{compile_input, CompileController};
|
||||
use rustc_metadata::cstore::CStore;
|
||||
use rustc_errors::registry::Registry;
|
||||
use syntax::codemap::FileName;
|
||||
use rustc_trans_utils::trans_crate::TransCrate;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
@ -51,7 +53,7 @@ fn main() {
|
||||
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();
|
||||
opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
|
||||
opts.maybe_sysroot = Some(sysroot);
|
||||
@ -60,16 +62,26 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
|
||||
}
|
||||
|
||||
let descriptions = Registry::new(&rustc::DIAGNOSTICS);
|
||||
let cstore = Rc::new(CStore::new(Box::new(rustc_trans::LlvmMetadataLoader)));
|
||||
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));
|
||||
(sess, cstore)
|
||||
(sess, cstore, trans)
|
||||
}
|
||||
|
||||
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 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
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) test.rs
|
||||
$(call RUN,test $(RUSTC))
|
@ -1,87 +0,0 @@
|
||||
// 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 @@
|
||||
extern crate getopts;
|
||||
extern crate rustc;
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_trans_utils;
|
||||
extern crate syntax;
|
||||
extern crate rustc_errors as errors;
|
||||
|
||||
@ -25,6 +26,7 @@ use rustc::middle::cstore::CrateStore;
|
||||
use rustc::session::Session;
|
||||
use rustc::session::config::{self, Input};
|
||||
use rustc_driver::{driver, CompilerCalls, Compilation};
|
||||
use rustc_trans_utils::trans_crate::TransCrate;
|
||||
use syntax::ast;
|
||||
|
||||
use std::path::PathBuf;
|
||||
@ -46,6 +48,7 @@ impl<'a> CompilerCalls<'a> for TestCalls {
|
||||
}
|
||||
|
||||
fn late_callback(&mut self,
|
||||
_: &TransCrate,
|
||||
_: &getopts::Matches,
|
||||
_: &Session,
|
||||
_: &CrateStore,
|
||||
|
Loading…
Reference in New Issue
Block a user