1+ use libloading:: Library ;
12use rustc_ast:: mut_visit:: { visit_clobber, MutVisitor , * } ;
23use rustc_ast:: ptr:: P ;
34use rustc_ast:: { self as ast, AttrVec , BlockCheckMode } ;
@@ -7,7 +8,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
78use rustc_data_structures:: jobserver;
89use rustc_data_structures:: sync:: Lrc ;
910use rustc_errors:: registry:: Registry ;
10- use rustc_metadata:: dynamic_lib:: DynamicLibrary ;
1111#[ cfg( parallel_compiler) ]
1212use rustc_middle:: ty:: tls;
1313use rustc_parse:: validate_attr;
@@ -39,6 +39,9 @@ use std::sync::{Arc, Mutex};
3939use std:: thread;
4040use tracing:: info;
4141
42+ /// Function pointer type that constructs a new CodegenBackend.
43+ pub type MakeBackendFn = fn ( ) -> Box < dyn CodegenBackend > ;
44+
4245/// Adds `target_feature = "..."` cfgs for a variety of platform
4346/// specific features (SSE, NEON etc.).
4447///
@@ -211,28 +214,24 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals<F: FnOnce() -> R + Se
211214 } )
212215}
213216
214- fn load_backend_from_dylib ( path : & Path ) -> fn ( ) -> Box < dyn CodegenBackend > {
215- let lib = DynamicLibrary :: open ( path) . unwrap_or_else ( |err| {
216- let err = format ! ( "couldn't load codegen backend {:?}: {:? }" , path, err) ;
217+ fn load_backend_from_dylib ( path : & Path ) -> MakeBackendFn {
218+ let lib = unsafe { Library :: new ( path) } . unwrap_or_else ( |err| {
219+ let err = format ! ( "couldn't load codegen backend {:?}: {}" , path, err) ;
217220 early_error ( ErrorOutputType :: default ( ) , & err) ;
218221 } ) ;
219- unsafe {
220- match lib. symbol ( "__rustc_codegen_backend" ) {
221- Ok ( f) => {
222- mem:: forget ( lib) ;
223- mem:: transmute :: < * mut u8 , _ > ( f)
224- }
225- Err ( e) => {
226- let err = format ! (
227- "couldn't load codegen backend as it \
228- doesn't export the `__rustc_codegen_backend` \
229- symbol: {:?}",
230- e
231- ) ;
232- early_error ( ErrorOutputType :: default ( ) , & err) ;
233- }
234- }
235- }
222+
223+ let backend_sym = unsafe { lib. get :: < MakeBackendFn > ( b"__rustc_codegen_backend" ) }
224+ . unwrap_or_else ( |e| {
225+ let err = format ! ( "couldn't load codegen backend: {}" , e) ;
226+ early_error ( ErrorOutputType :: default ( ) , & err) ;
227+ } ) ;
228+
229+ // Intentionally leak the dynamic library. We can't ever unload it
230+ // since the library can make things that will live arbitrarily long.
231+ let backend_sym = unsafe { backend_sym. into_raw ( ) } ;
232+ mem:: forget ( lib) ;
233+
234+ * backend_sym
236235}
237236
238237/// Get the codegen backend based on the name and specified sysroot.
@@ -380,10 +379,7 @@ fn sysroot_candidates() -> Vec<PathBuf> {
380379 }
381380}
382381
383- pub fn get_codegen_sysroot (
384- maybe_sysroot : & Option < PathBuf > ,
385- backend_name : & str ,
386- ) -> fn ( ) -> Box < dyn CodegenBackend > {
382+ pub fn get_codegen_sysroot ( maybe_sysroot : & Option < PathBuf > , backend_name : & str ) -> MakeBackendFn {
387383 // For now we only allow this function to be called once as it'll dlopen a
388384 // few things, which seems to work best if we only do that once. In
389385 // general this assertion never trips due to the once guard in `get_codegen_backend`,
0 commit comments