Hot plug rustc_trans

This commit is contained in:
bjorn3 2018-01-01 12:17:07 +01:00
parent 6dffaa9175
commit 9315ed45c5
6 changed files with 204 additions and 0 deletions

12
src/Cargo.lock generated
View File

@ -1021,6 +1021,16 @@ dependencies = [
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libloading"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libssh2-sys"
version = "0.2.6"
@ -2128,6 +2138,7 @@ version = "0.0.0"
dependencies = [
"ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_back 0.0.0",
@ -2971,6 +2982,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b"
"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121"
"checksum libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6eeae66e7b1c995de45cb4e65c5ab438a96a7b4077e448645d4048dc753ad357"
"checksum libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd38073de8f7965d0c17d30546d4bb6da311ab428d1c7a3fc71dff7f9d4979b9"
"checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75"
"checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"

View File

@ -197,6 +197,9 @@ pub fn get_trans(sess: &Session) -> Box<TransCrate> {
Some("metadata_only") => {
rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new(&sess)
}
Some(filename) if filename.starts_with("/") => {
rustc_trans_utils::trans_crate::ExternTransCrate::new(&sess, filename)
}
Some(trans_name) => sess.fatal(&format!("Invalid trans {}", trans_name)),
}
}

View File

@ -56,6 +56,7 @@ 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;
@ -250,6 +251,8 @@ impl TransCrate for LlvmTransCrate {
}
}
hot_pluggable_trans_crate!(|sess| { LlvmTransCrate::new(sess) });
struct ModuleTranslation {
/// The name of the module. When the crate may be saved between
/// compilations, incremental compilation requires that name be

View File

@ -13,6 +13,7 @@ test = false
ar = "0.3.0"
flate2 = "1.0"
log = "0.4"
libloading = "0.4"
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }

View File

@ -31,6 +31,7 @@ extern crate ar;
extern crate flate2;
#[macro_use]
extern crate log;
extern crate libloading;
#[macro_use]
extern crate rustc;
@ -42,6 +43,8 @@ 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;
@ -50,6 +53,7 @@ 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;

View File

@ -24,6 +24,7 @@
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;
@ -73,6 +74,186 @@ pub trait TransCrate {
) -> Result<(), CompileIncomplete>;
}
#[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))
}
#[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));
}
}
}
}
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 _
))
}
}
}
pub struct DummyTransCrate;
impl TransCrate for DummyTransCrate {