Skip to content

Commit 9315ed4

Browse files
committed
Hot plug rustc_trans
1 parent 6dffaa9 commit 9315ed4

File tree

6 files changed

+204
-0
lines changed

6 files changed

+204
-0
lines changed

src/Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/librustc_driver/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ pub fn get_trans(sess: &Session) -> Box<TransCrate> {
197197
Some("metadata_only") => {
198198
rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new(&sess)
199199
}
200+
Some(filename) if filename.starts_with("/") => {
201+
rustc_trans_utils::trans_crate::ExternTransCrate::new(&sess, filename)
202+
}
200203
Some(trans_name) => sess.fatal(&format!("Invalid trans {}", trans_name)),
201204
}
202205
}

src/librustc_trans/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ extern crate rustc_demangle;
5656
extern crate rustc_incremental;
5757
extern crate rustc_llvm as llvm;
5858
extern crate rustc_platform_intrinsics as intrinsics;
59+
#[macro_use]
5960
extern crate rustc_trans_utils;
6061

6162
#[macro_use] extern crate log;
@@ -250,6 +251,8 @@ impl TransCrate for LlvmTransCrate {
250251
}
251252
}
252253

254+
hot_pluggable_trans_crate!(|sess| { LlvmTransCrate::new(sess) });
255+
253256
struct ModuleTranslation {
254257
/// The name of the module. When the crate may be saved between
255258
/// compilations, incremental compilation requires that name be

src/librustc_trans_utils/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ test = false
1313
ar = "0.3.0"
1414
flate2 = "1.0"
1515
log = "0.4"
16+
libloading = "0.4"
1617

1718
syntax = { path = "../libsyntax" }
1819
syntax_pos = { path = "../libsyntax_pos" }

src/librustc_trans_utils/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ extern crate ar;
3131
extern crate flate2;
3232
#[macro_use]
3333
extern crate log;
34+
extern crate libloading;
3435

3536
#[macro_use]
3637
extern crate rustc;
@@ -42,6 +43,8 @@ extern crate syntax;
4243
extern crate syntax_pos;
4344
extern crate rustc_data_structures;
4445

46+
pub extern crate rustc as __rustc;
47+
4548
use rustc::ty::{TyCtxt, Instance};
4649
use rustc::hir;
4750
use rustc::hir::def_id::LOCAL_CRATE;
@@ -50,6 +53,7 @@ use rustc::util::nodemap::NodeSet;
5053

5154
pub mod diagnostics;
5255
pub mod link;
56+
#[macro_export]
5357
pub mod trans_crate;
5458
pub mod symbol_names;
5559
pub mod symbol_names_test;

src/librustc_trans_utils/trans_crate.rs

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use std::any::Any;
2525
use std::io::prelude::*;
2626
use std::io::{self, Cursor};
27+
use std::ffi::OsStr;
2728
use std::fs::File;
2829
use std::path::Path;
2930
use std::sync::mpsc;
@@ -73,6 +74,186 @@ pub trait TransCrate {
7374
) -> Result<(), CompileIncomplete>;
7475
}
7576

77+
#[macro_export]
78+
macro_rules! hot_pluggable_trans_crate {
79+
(|$sess:ident| { $body:expr }) => {
80+
use $crate::__rustc::ty::maps::Providers;
81+
#[no_mangle]
82+
pub extern "C" fn __rustc_backend_new($sess: &Session) -> *mut Box<TransCrate> {
83+
let trans_crate = { $body };
84+
Box::into_raw(Box::new(trans_crate))
85+
}
86+
87+
#[no_mangle]
88+
pub extern "C" fn __rustc_backend_metadata_loader(
89+
trans_crate: *const Box<TransCrate>
90+
) -> *mut Box<MetadataLoader> {
91+
let trans_crate = unsafe { &*trans_crate };
92+
let metadata_loader = trans_crate.metadata_loader();
93+
Box::into_raw(Box::new(metadata_loader))
94+
}
95+
96+
#[no_mangle]
97+
pub extern "C" fn __rustc_backend_provide(
98+
trans_crate: *const Box<TransCrate>,
99+
providers: *mut Providers
100+
) {
101+
let trans_crate = unsafe { &*trans_crate };
102+
let providers = unsafe { &mut *providers };
103+
trans_crate.provide(providers);
104+
}
105+
106+
#[no_mangle]
107+
pub extern "C" fn __rustc_backend_provide_extern(
108+
trans_crate: *const Box<TransCrate>,
109+
providers: *mut Providers
110+
) {
111+
let trans_crate = unsafe { &*trans_crate };
112+
let providers = unsafe { &mut *providers };
113+
trans_crate.provide_extern(providers);
114+
}
115+
116+
#[no_mangle]
117+
pub extern "C" fn __rustc_backend_trans_crate<'a, 'tcx: 'a>(
118+
trans_crate: *const Box<TransCrate>,
119+
tcx: *mut TyCtxt<'a, 'tcx, 'tcx>,
120+
rx: *mut mpsc::Receiver<Box<Any + Send>>
121+
) -> *mut Box<Any> {
122+
let trans_crate = unsafe { &*trans_crate };
123+
let tcx = unsafe { *tcx };
124+
let rx = unsafe { *Box::from_raw(rx) };
125+
let trans = trans_crate.trans_crate(tcx, rx);
126+
Box::into_raw(Box::new(trans))
127+
}
128+
129+
#[no_mangle]
130+
pub extern "C" fn __rustc_backend_join_trans_and_link(
131+
trans_crate: *const Box<TransCrate>,
132+
trans: *mut Box<Any>,
133+
sess: *const Session,
134+
dep_graph: *const DepGraph,
135+
outputs: *const OutputFilenames
136+
) -> *mut Result<(), CompileIncomplete> {
137+
let trans_crate = unsafe { &*trans_crate };
138+
let trans = unsafe { *Box::from_raw(trans) };
139+
let sess = unsafe { &*sess };
140+
let dep_graph = unsafe { &*dep_graph };
141+
let outputs = unsafe { &*outputs };
142+
let result = trans_crate.join_trans_and_link(trans, sess, dep_graph, outputs);
143+
Box::into_raw(Box::new(result))
144+
}
145+
}
146+
}
147+
148+
pub struct ExternTransCrate {
149+
lib: ::libloading::Library,
150+
backend: Box<Box<TransCrate>>,
151+
}
152+
153+
macro_rules! get_symbol {
154+
(($lib:expr) . $name:ident : $type:ty) => {
155+
let $name: ::libloading::Symbol<$type> = $lib.get(stringify!($name).as_bytes()).unwrap();
156+
}
157+
}
158+
159+
impl ExternTransCrate {
160+
pub fn new<P: AsRef<OsStr>>(sess: &Session, filename: P) -> Box<TransCrate> {
161+
use libloading::*;
162+
let filename = filename.as_ref();
163+
match Library::new(filename) {
164+
Ok(lib) => {
165+
let backend = unsafe {
166+
get_symbol!((lib).__rustc_backend_new:
167+
unsafe extern "C" fn(&Session) -> *mut Box<TransCrate>);
168+
Box::from_raw(__rustc_backend_new(sess))
169+
};
170+
Box::new(ExternTransCrate {
171+
lib,
172+
backend,
173+
})
174+
}
175+
Err(err) => {
176+
sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", filename, err));
177+
}
178+
}
179+
}
180+
}
181+
182+
impl TransCrate for ExternTransCrate {
183+
fn metadata_loader(&self) -> Box<MetadataLoader> {
184+
unsafe {
185+
get_symbol!((self.lib).__rustc_backend_metadata_loader:
186+
unsafe extern "C" fn(*const Box<TransCrate>) -> *mut Box<MetadataLoader>);
187+
*Box::from_raw(__rustc_backend_metadata_loader(self.backend.as_ref() as *const _))
188+
}
189+
}
190+
191+
fn provide(&self, providers: &mut Providers) {
192+
unsafe {
193+
get_symbol!((self.lib).__rustc_backend_provide:
194+
unsafe extern "C" fn(*const Box<TransCrate>, *mut Providers));
195+
__rustc_backend_provide(self.backend.as_ref() as *const _, providers as *mut _);
196+
}
197+
}
198+
199+
fn provide_extern(&self, providers: &mut Providers) {
200+
unsafe {
201+
get_symbol!((self.lib).__rustc_backend_provide_extern:
202+
unsafe extern "C" fn(*const Box<TransCrate>, *mut Providers));
203+
__rustc_backend_provide_extern(self.backend.as_ref() as *const _, providers as *mut _);
204+
}
205+
}
206+
207+
fn trans_crate<'a, 'tcx>(
208+
&self,
209+
mut tcx: TyCtxt<'a, 'tcx, 'tcx>,
210+
rx: mpsc::Receiver<Box<Any + Send>>
211+
) -> Box<Any> {
212+
unsafe {
213+
get_symbol!((self.lib).__rustc_backend_trans_crate:
214+
unsafe extern "C" fn(
215+
*const Box<TransCrate>,
216+
*mut TyCtxt<'a, 'tcx, 'tcx>,
217+
*mut mpsc::Receiver<Box<Any + Send>>
218+
) -> *mut Box<Any>
219+
);
220+
let rx = Box::new(rx);
221+
*Box::from_raw(__rustc_backend_trans_crate(
222+
self.backend.as_ref() as *const _,
223+
&mut tcx as *mut _,
224+
Box::into_raw(rx) as *mut _
225+
))
226+
}
227+
}
228+
229+
fn join_trans_and_link(
230+
&self,
231+
trans: Box<Any>,
232+
sess: &Session,
233+
dep_graph: &DepGraph,
234+
outputs: &OutputFilenames,
235+
) -> Result<(), CompileIncomplete> {
236+
unsafe {
237+
get_symbol!((self.lib).__rustc_backend_join_trans_and_link:
238+
unsafe extern "C" fn(
239+
*const Box<TransCrate>,
240+
*mut Box<Any>,
241+
*const Session,
242+
*const DepGraph,
243+
*const OutputFilenames
244+
) -> *mut Result<(), CompileIncomplete>
245+
);
246+
*Box::from_raw(__rustc_backend_join_trans_and_link(
247+
self.backend.as_ref() as *const _,
248+
Box::into_raw(Box::new(trans)) as *mut _,
249+
sess as *const _,
250+
dep_graph as *const _,
251+
outputs as *const _
252+
))
253+
}
254+
}
255+
}
256+
76257
pub struct DummyTransCrate;
77258

78259
impl TransCrate for DummyTransCrate {

0 commit comments

Comments
 (0)