From 9315ed45c5d221b868848f8db9ba4a5be155e008 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 1 Jan 2018 12:17:07 +0100 Subject: [PATCH] Hot plug rustc_trans --- src/Cargo.lock | 12 ++ src/librustc_driver/lib.rs | 3 + src/librustc_trans/lib.rs | 3 + src/librustc_trans_utils/Cargo.toml | 1 + src/librustc_trans_utils/lib.rs | 4 + src/librustc_trans_utils/trans_crate.rs | 181 ++++++++++++++++++++++++ 6 files changed, 204 insertions(+) diff --git a/src/Cargo.lock b/src/Cargo.lock index 6f919fd1acd..1deb89092e6 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -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" diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index a1bfd2a4774..b5619a0eac0 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -197,6 +197,9 @@ 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::ExternTransCrate::new(&sess, filename) + } Some(trans_name) => sess.fatal(&format!("Invalid trans {}", trans_name)), } } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index d1dec63e0d8..d03086481a4 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -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 diff --git a/src/librustc_trans_utils/Cargo.toml b/src/librustc_trans_utils/Cargo.toml index 7a01b6d261a..6d433bdef3e 100644 --- a/src/librustc_trans_utils/Cargo.toml +++ b/src/librustc_trans_utils/Cargo.toml @@ -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" } diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs index 4920732c41f..029a14a46e6 100644 --- a/src/librustc_trans_utils/lib.rs +++ b/src/librustc_trans_utils/lib.rs @@ -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; diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs index 9d42091e132..31bfe5b02a2 100644 --- a/src/librustc_trans_utils/trans_crate.rs +++ b/src/librustc_trans_utils/trans_crate.rs @@ -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 { + 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 + ) -> *mut Box { + 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, + 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, + 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, + tcx: *mut TyCtxt<'a, 'tcx, 'tcx>, + rx: *mut mpsc::Receiver> + ) -> *mut Box { + 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, + trans: *mut Box, + 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>, +} + +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>(sess: &Session, filename: P) -> Box { + 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); + 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 { + unsafe { + get_symbol!((self.lib).__rustc_backend_metadata_loader: + unsafe extern "C" fn(*const Box) -> *mut Box); + *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, *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, *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 { + unsafe { + get_symbol!((self.lib).__rustc_backend_trans_crate: + unsafe extern "C" fn( + *const Box, + *mut TyCtxt<'a, 'tcx, 'tcx>, + *mut mpsc::Receiver> + ) -> *mut Box + ); + 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, + 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, + *mut Box, + *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 {