@@ -19,14 +19,16 @@ use rustc_span::edit_distance::find_best_match_for_name;
1919use rustc_span:: edition:: Edition ;
2020use rustc_span:: source_map:: FileLoader ;
2121use rustc_span:: symbol:: { sym, Symbol } ;
22+ use rustc_target:: spec:: Target ;
2223use session:: { CompilerIO , EarlyErrorHandler } ;
23- use std:: env;
2424use std:: env:: consts:: { DLL_PREFIX , DLL_SUFFIX } ;
2525use std:: mem;
26+ use std:: ops:: Deref ;
2627use std:: path:: { Path , PathBuf } ;
2728use std:: sync:: atomic:: { AtomicBool , Ordering } ;
2829use std:: sync:: { Arc , OnceLock } ;
2930use std:: thread;
31+ use std:: { env, iter} ;
3032
3133/// Function pointer type that constructs a new CodegenBackend.
3234pub type MakeBackendFn = fn ( ) -> Box < dyn CodegenBackend > ;
@@ -75,24 +77,41 @@ pub fn create_session(
7577 } ;
7678
7779 let ( codegen_backend, target_cfg) = match make_codegen_backend {
78- Some ( make_codegen_backend) => {
79- let backend = make_codegen_backend ( & sopts) ;
80+ None => {
81+ // Build a target without override, so that it can override the backend if needed
82+ let target = config:: build_target_config ( handler, & sopts, None , & sysroot) ;
83+
84+ let backend = get_codegen_backend (
85+ handler,
86+ & sysroot,
87+ sopts. unstable_opts . codegen_backend . as_deref ( ) ,
88+ & target,
89+ ) ;
8090
8191 // target_override is documented to be called before init(), so this is okay
8292 let target_override = backend. target_override ( & sopts) ;
8393
94+ // Assert that we don't use target's override of the backend and
95+ // backend's override of the target at the same time
96+ if sopts. unstable_opts . codegen_backend . is_none ( )
97+ && target. default_codegen_backend . is_some ( )
98+ && target_override. is_some ( )
99+ {
100+ rustc_middle:: bug!(
101+ "Codegen backend requested target override even though the target requested the backend"
102+ ) ;
103+ }
104+
105+ // Re-build target with the (potential) override
84106 let target = config:: build_target_config ( handler, & sopts, target_override, & sysroot) ;
85107
86108 ( backend, target)
87109 }
88- None => {
89- let _target = config:: build_target_config ( handler, & sopts, None , & sysroot) ;
110+ Some ( make_codegen_backend) => {
111+ // N.B. `make_codegen_backend` takes precedence over `target.default_codegen_backend`,
112+ // which is ignored in this case.
90113
91- let backend = get_codegen_backend (
92- handler,
93- & sopts. maybe_sysroot ,
94- sopts. unstable_opts . codegen_backend . as_deref ( ) ,
95- ) ;
114+ let backend = make_codegen_backend ( & sopts) ;
96115
97116 // target_override is documented to be called before init(), so this is okay
98117 let target_override = backend. target_override ( & sopts) ;
@@ -292,21 +311,25 @@ fn load_backend_from_dylib(handler: &EarlyErrorHandler, path: &Path) -> MakeBack
292311/// A name of `None` indicates that the default backend should be used.
293312pub fn get_codegen_backend (
294313 handler : & EarlyErrorHandler ,
295- maybe_sysroot : & Option < PathBuf > ,
314+ sysroot : & Path ,
296315 backend_name : Option < & str > ,
316+ target : & Target ,
297317) -> Box < dyn CodegenBackend > {
298318 static LOAD : OnceLock < unsafe fn ( ) -> Box < dyn CodegenBackend > > = OnceLock :: new ( ) ;
299319
300320 let load = LOAD . get_or_init ( || {
301- let default_codegen_backend = option_env ! ( "CFG_DEFAULT_CODEGEN_BACKEND" ) . unwrap_or ( "llvm" ) ;
321+ let backend = backend_name
322+ . or ( target. default_codegen_backend . as_deref ( ) )
323+ . or ( option_env ! ( "CFG_DEFAULT_CODEGEN_BACKEND" ) )
324+ . unwrap_or ( "llvm" ) ;
302325
303- match backend_name . unwrap_or ( default_codegen_backend ) {
326+ match backend {
304327 filename if filename. contains ( '.' ) => {
305328 load_backend_from_dylib ( handler, filename. as_ref ( ) )
306329 }
307330 #[ cfg( feature = "llvm" ) ]
308331 "llvm" => rustc_codegen_llvm:: LlvmCodegenBackend :: new,
309- backend_name => get_codegen_sysroot ( handler, maybe_sysroot , backend_name) ,
332+ backend_name => get_codegen_sysroot ( handler, sysroot , backend_name) ,
310333 }
311334 } ) ;
312335
@@ -340,7 +363,7 @@ fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> {
340363
341364fn get_codegen_sysroot (
342365 handler : & EarlyErrorHandler ,
343- maybe_sysroot : & Option < PathBuf > ,
366+ sysroot : & Path ,
344367 backend_name : & str ,
345368) -> MakeBackendFn {
346369 // For now we only allow this function to be called once as it'll dlopen a
@@ -357,9 +380,8 @@ fn get_codegen_sysroot(
357380 let target = session:: config:: host_triple ( ) ;
358381 let sysroot_candidates = sysroot_candidates ( ) ;
359382
360- let sysroot = maybe_sysroot
361- . iter ( )
362- . chain ( sysroot_candidates. iter ( ) )
383+ let sysroot = iter:: once ( sysroot)
384+ . chain ( sysroot_candidates. iter ( ) . map ( <_ >:: deref) )
363385 . map ( |sysroot| {
364386 filesearch:: make_target_lib_path ( sysroot, target) . with_file_name ( "codegen-backends" )
365387 } )
0 commit comments