1
+ use libloading:: Library ;
1
2
use rustc_ast:: mut_visit:: { visit_clobber, MutVisitor , * } ;
2
3
use rustc_ast:: ptr:: P ;
3
4
use rustc_ast:: { self as ast, AttrVec , BlockCheckMode } ;
@@ -7,7 +8,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
7
8
use rustc_data_structures:: jobserver;
8
9
use rustc_data_structures:: sync:: Lrc ;
9
10
use rustc_errors:: registry:: Registry ;
10
- use rustc_metadata:: dynamic_lib:: DynamicLibrary ;
11
11
#[ cfg( parallel_compiler) ]
12
12
use rustc_middle:: ty:: tls;
13
13
use rustc_parse:: validate_attr;
@@ -39,6 +39,9 @@ use std::sync::{Arc, Mutex};
39
39
use std:: thread;
40
40
use tracing:: info;
41
41
42
+ /// Function pointer type that constructs a new CodegenBackend.
43
+ pub type MakeBackendFn = fn ( ) -> Box < dyn CodegenBackend > ;
44
+
42
45
/// Adds `target_feature = "..."` cfgs for a variety of platform
43
46
/// specific features (SSE, NEON etc.).
44
47
///
@@ -211,28 +214,24 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals<F: FnOnce() -> R + Se
211
214
} )
212
215
}
213
216
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) ;
217
220
early_error ( ErrorOutputType :: default ( ) , & err) ;
218
221
} ) ;
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
236
235
}
237
236
238
237
/// Get the codegen backend based on the name and specified sysroot.
@@ -380,10 +379,7 @@ fn sysroot_candidates() -> Vec<PathBuf> {
380
379
}
381
380
}
382
381
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 {
387
383
// For now we only allow this function to be called once as it'll dlopen a
388
384
// few things, which seems to work best if we only do that once. In
389
385
// general this assertion never trips due to the once guard in `get_codegen_backend`,
0 commit comments