From ace502a10736dba186785ea439c50be75d0cfdfb Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 4 Jan 2018 12:40:11 +0100 Subject: [PATCH] Fix review comments --- src/librustc_driver/lib.rs | 81 ++++++++++++++++++++++++- src/librustc_trans/lib.rs | 7 ++- src/librustc_trans_utils/lib.rs | 2 - src/librustc_trans_utils/trans_crate.rs | 32 +--------- 4 files changed, 84 insertions(+), 38 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 558fd3b02be..14d14ab591e 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -189,6 +189,81 @@ pub mod rustc_trans { pub fn print_passes() {} } +fn load_backend_from_dylib(sess: &Session, backend_name: &str) -> Box { + use std::sync::mpsc; + use std::path::Path; + use syntax::symbol::Symbol; + 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_metadata::dynamic_lib::DynamicLibrary; + /// This prevents the dylib from being unloaded when there is still a TransCrate open + struct ExternTransCrate { + _lib: DynamicLibrary, + trans: Box, + } + impl TransCrate for ExternTransCrate { + fn print(&self, req: PrintRequest, sess: &Session) { + self.trans.print(req, sess); + } + fn target_features(&self, sess: &Session) -> Vec { + self.trans.target_features((sess)) + } + + fn metadata_loader(&self) -> Box { + self.trans.metadata_loader() + } + fn provide(&self, providers: &mut Providers) { + self.trans.provide(providers) + } + fn provide_extern(&self, providers: &mut Providers) { + self.trans.provide_extern(providers) + } + fn trans_crate<'a, 'tcx>( + &self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + rx: mpsc::Receiver> + ) -> Box { + self.trans.trans_crate(tcx, rx) + } + + fn join_trans_and_link( + &self, + trans: Box, + sess: &Session, + dep_graph: &DepGraph, + outputs: &OutputFilenames, + ) -> Result<(), CompileIncomplete> { + self.trans.join_trans_and_link(trans, sess, dep_graph, outputs) + } + } + + match DynamicLibrary::open(Some(Path::new(backend_name))) { + Ok(lib) => { + unsafe { + let trans = { + let __rustc_codegen_backend: unsafe fn(&Session) -> Box; + __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) + }; + Box::new(ExternTransCrate { + _lib: lib, + trans + }) + } + } + Err(err) => { + sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", backend_name, err)); + } + } +} + pub fn get_trans(sess: &Session) -> Box { let trans_name = sess.opts.debugging_opts.codegen_backend.clone(); match trans_name.as_ref().map(|s|&**s) { @@ -197,10 +272,10 @@ pub fn get_trans(sess: &Session) -> Box { Some("metadata_only") => { rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new(&sess) } - Some(filename) if filename.starts_with("/") => { - rustc_trans_utils::trans_crate::link_extern_backend(&sess, filename) + Some(filename) if filename.contains(".") => { + load_backend_from_dylib(&sess, &filename) } - Some(trans_name) => sess.fatal(&format!("Invalid trans {}", trans_name)), + Some(trans_name) => sess.fatal(&format!("Unknown codegen backend {}", trans_name)), } } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index d03086481a4..a2a7d0df2a9 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -56,7 +56,6 @@ extern crate rustc_demangle; extern crate rustc_incremental; extern crate rustc_llvm as llvm; extern crate rustc_platform_intrinsics as intrinsics; -#[macro_use] extern crate rustc_trans_utils; #[macro_use] extern crate log; @@ -251,7 +250,11 @@ impl TransCrate for LlvmTransCrate { } } -hot_pluggable_trans_crate!(|sess| { LlvmTransCrate::new(sess) }); +/// This is the entrypoint for a hot plugged rustc_trans +#[no_mangle] +pub extern "C" fn __rustc_codegen_backend(sess: &Session) -> Box { + LlvmTransCrate::new(sess) +} struct ModuleTranslation { /// The name of the module. When the crate may be saved between diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs index 029a14a46e6..bfecb201983 100644 --- a/src/librustc_trans_utils/lib.rs +++ b/src/librustc_trans_utils/lib.rs @@ -31,7 +31,6 @@ extern crate ar; extern crate flate2; #[macro_use] extern crate log; -extern crate libloading; #[macro_use] extern crate rustc; @@ -53,7 +52,6 @@ use rustc::util::nodemap::NodeSet; pub mod diagnostics; pub mod link; -#[macro_export] pub mod trans_crate; pub mod symbol_names; pub mod symbol_names_test; diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs index 0def49132e4..33adf24374a 100644 --- a/src/librustc_trans_utils/trans_crate.rs +++ b/src/librustc_trans_utils/trans_crate.rs @@ -24,7 +24,6 @@ use std::any::Any; use std::io::prelude::*; use std::io::{self, Cursor}; -use std::ffi::OsStr; use std::fs::File; use std::path::Path; use std::sync::mpsc; @@ -41,7 +40,7 @@ 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 MetadataLoader; +use rustc::middle::cstore::MetadataLoader; use rustc::dep_graph::DepGraph; use rustc_back::target::Target; use rustc_mir::monomorphize::collector; @@ -74,35 +73,6 @@ pub trait TransCrate { ) -> Result<(), CompileIncomplete>; } -#[macro_export] -macro_rules! hot_pluggable_trans_crate { - (|$sess:ident| { $body:expr }) => { - #[no_mangle] - pub fn __rustc_backend_new($sess: &Session) -> Box { - { $body } - } - } -} - -pub fn link_extern_backend>(sess: &Session, filename: P) -> Box { - use libloading::*; - let filename = filename.as_ref(); - match Library::new(filename) { - Ok(lib) => { - unsafe { - let __rustc_backend_new: Symbol Box>; - __rustc_backend_new = lib.get(b"__rustc_backend_new") - .expect("Couldnt load codegen backend as it\ - doesnt export the __rustc_backend_new symbol"); - __rustc_backend_new(sess) - } - } - Err(err) => { - sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", filename, err)); - } - } -} - pub struct DummyTransCrate; impl TransCrate for DummyTransCrate {