Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Cleanup hot plug codegen backend code
  • Loading branch information
bjorn3 committed Jan 19, 2018
commit 2d241f66fef30b27fad377ed49fe978541ac0ed8
2 changes: 1 addition & 1 deletion src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ pub fn get_trans(sess: &Session) -> Box<TransCrate> {
rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new(&sess)
}
Some(filename) if filename.starts_with("/") => {
rustc_trans_utils::trans_crate::ExternTransCrate::new(&sess, filename)
rustc_trans_utils::trans_crate::link_extern_backend(&sess, filename)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, can you move that function here? I think rustc_driver should be the one with the libloading dependency.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, if you move that here you can get rid of the libloading dependency by using rustc_metadata::dynamic_lib.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didnt know about rustc_metadata::dynamic_lib.

}
Some(trans_name) => sess.fatal(&format!("Invalid trans {}", trans_name)),
}
Expand Down
181 changes: 15 additions & 166 deletions src/librustc_trans_utils/trans_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,179 +77,28 @@ pub trait TransCrate {
#[macro_export]
macro_rules! hot_pluggable_trans_crate {
(|$sess:ident| { $body:expr }) => {
use $crate::__rustc::ty::maps::Providers;
#[no_mangle]
pub extern "C" fn __rustc_backend_new($sess: &Session) -> *mut Box<TransCrate> {
let trans_crate = { $body };
Box::into_raw(Box::new(trans_crate))
pub fn __rustc_backend_new($sess: &Session) -> Box<TransCrate> {
{ $body }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need the braces here - also, do we really need a macro now?
I think the name should be __rustc_codegen_backend.

}

#[no_mangle]
pub extern "C" fn __rustc_backend_metadata_loader(
trans_crate: *const Box<TransCrate>
) -> *mut Box<MetadataLoader> {
let trans_crate = unsafe { &*trans_crate };
let metadata_loader = trans_crate.metadata_loader();
Box::into_raw(Box::new(metadata_loader))
}

#[no_mangle]
pub extern "C" fn __rustc_backend_provide(
trans_crate: *const Box<TransCrate>,
providers: *mut Providers
) {
let trans_crate = unsafe { &*trans_crate };
let providers = unsafe { &mut *providers };
trans_crate.provide(providers);
}

#[no_mangle]
pub extern "C" fn __rustc_backend_provide_extern(
trans_crate: *const Box<TransCrate>,
providers: *mut Providers
) {
let trans_crate = unsafe { &*trans_crate };
let providers = unsafe { &mut *providers };
trans_crate.provide_extern(providers);
}

#[no_mangle]
pub extern "C" fn __rustc_backend_trans_crate<'a, 'tcx: 'a>(
trans_crate: *const Box<TransCrate>,
tcx: *mut TyCtxt<'a, 'tcx, 'tcx>,
rx: *mut mpsc::Receiver<Box<Any + Send>>
) -> *mut Box<Any> {
let trans_crate = unsafe { &*trans_crate };
let tcx = unsafe { *tcx };
let rx = unsafe { *Box::from_raw(rx) };
let trans = trans_crate.trans_crate(tcx, rx);
Box::into_raw(Box::new(trans))
}

#[no_mangle]
pub extern "C" fn __rustc_backend_join_trans_and_link(
trans_crate: *const Box<TransCrate>,
trans: *mut Box<Any>,
sess: *const Session,
dep_graph: *const DepGraph,
outputs: *const OutputFilenames
) -> *mut Result<(), CompileIncomplete> {
let trans_crate = unsafe { &*trans_crate };
let trans = unsafe { *Box::from_raw(trans) };
let sess = unsafe { &*sess };
let dep_graph = unsafe { &*dep_graph };
let outputs = unsafe { &*outputs };
let result = trans_crate.join_trans_and_link(trans, sess, dep_graph, outputs);
Box::into_raw(Box::new(result))
}
}
}

pub struct ExternTransCrate {
lib: ::libloading::Library,
backend: Box<Box<TransCrate>>,
}

macro_rules! get_symbol {
(($lib:expr) . $name:ident : $type:ty) => {
let $name: ::libloading::Symbol<$type> = $lib.get(stringify!($name).as_bytes()).unwrap();
}
}

impl ExternTransCrate {
pub fn new<P: AsRef<OsStr>>(sess: &Session, filename: P) -> Box<TransCrate> {
use libloading::*;
let filename = filename.as_ref();
match Library::new(filename) {
Ok(lib) => {
let backend = unsafe {
get_symbol!((lib).__rustc_backend_new:
unsafe extern "C" fn(&Session) -> *mut Box<TransCrate>);
Box::from_raw(__rustc_backend_new(sess))
};
Box::new(ExternTransCrate {
lib,
backend,
})
}
Err(err) => {
sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", filename, err));
pub fn link_extern_backend<P: AsRef<OsStr>>(sess: &Session, filename: P) -> Box<TransCrate> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you rename this to load_backend_from_dylib?

use libloading::*;
let filename = filename.as_ref();
match Library::new(filename) {
Ok(lib) => {
unsafe {
let __rustc_backend_new: Symbol<unsafe fn(&Session) -> Box<TransCrate>>;
__rustc_backend_new = lib.get(b"__rustc_backend_new")
.expect("Couldnt load codegen backend as it\
doesnt export the __rustc_backend_new symbol");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't you match on this to use sess.fatal here? Also, missing ' in Couldn't.

__rustc_backend_new(sess)
}
}
}
}

impl TransCrate for ExternTransCrate {
fn metadata_loader(&self) -> Box<MetadataLoader> {
unsafe {
get_symbol!((self.lib).__rustc_backend_metadata_loader:
unsafe extern "C" fn(*const Box<TransCrate>) -> *mut Box<MetadataLoader>);
*Box::from_raw(__rustc_backend_metadata_loader(self.backend.as_ref() as *const _))
}
}

fn provide(&self, providers: &mut Providers) {
unsafe {
get_symbol!((self.lib).__rustc_backend_provide:
unsafe extern "C" fn(*const Box<TransCrate>, *mut Providers));
__rustc_backend_provide(self.backend.as_ref() as *const _, providers as *mut _);
}
}

fn provide_extern(&self, providers: &mut Providers) {
unsafe {
get_symbol!((self.lib).__rustc_backend_provide_extern:
unsafe extern "C" fn(*const Box<TransCrate>, *mut Providers));
__rustc_backend_provide_extern(self.backend.as_ref() as *const _, providers as *mut _);
}
}

fn trans_crate<'a, 'tcx>(
&self,
mut tcx: TyCtxt<'a, 'tcx, 'tcx>,
rx: mpsc::Receiver<Box<Any + Send>>
) -> Box<Any> {
unsafe {
get_symbol!((self.lib).__rustc_backend_trans_crate:
unsafe extern "C" fn(
*const Box<TransCrate>,
*mut TyCtxt<'a, 'tcx, 'tcx>,
*mut mpsc::Receiver<Box<Any + Send>>
) -> *mut Box<Any>
);
let rx = Box::new(rx);
*Box::from_raw(__rustc_backend_trans_crate(
self.backend.as_ref() as *const _,
&mut tcx as *mut _,
Box::into_raw(rx) as *mut _
))
}
}

fn join_trans_and_link(
&self,
trans: Box<Any>,
sess: &Session,
dep_graph: &DepGraph,
outputs: &OutputFilenames,
) -> Result<(), CompileIncomplete> {
unsafe {
get_symbol!((self.lib).__rustc_backend_join_trans_and_link:
unsafe extern "C" fn(
*const Box<TransCrate>,
*mut Box<Any>,
*const Session,
*const DepGraph,
*const OutputFilenames
) -> *mut Result<(), CompileIncomplete>
);
*Box::from_raw(__rustc_backend_join_trans_and_link(
self.backend.as_ref() as *const _,
Box::into_raw(Box::new(trans)) as *mut _,
sess as *const _,
dep_graph as *const _,
outputs as *const _
))
Err(err) => {
sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", filename, err));
}
}
}
Expand Down