@@ -334,6 +334,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
334
334
pub output_filenames : Arc < OutputFilenames > ,
335
335
pub invocation_temp : Option < String > ,
336
336
pub module_config : Arc < ModuleConfig > ,
337
+ pub allocator_config : Arc < ModuleConfig > ,
337
338
pub tm_factory : TargetMachineFactoryFn < B > ,
338
339
pub msvc_imps_needed : bool ,
339
340
pub is_pe_coff : bool ,
@@ -794,12 +795,19 @@ pub(crate) fn compute_per_cgu_lto_type(
794
795
sess_lto : & Lto ,
795
796
opts : & config:: Options ,
796
797
sess_crate_types : & [ CrateType ] ,
798
+ module_kind : ModuleKind ,
797
799
) -> ComputedLtoType {
798
800
// If the linker does LTO, we don't have to do it. Note that we
799
801
// keep doing full LTO, if it is requested, as not to break the
800
802
// assumption that the output will be a single module.
801
803
let linker_does_lto = opts. cg . linker_plugin_lto . enabled ( ) ;
802
804
805
+ // When we're automatically doing ThinLTO for multi-codegen-unit
806
+ // builds we don't actually want to LTO the allocator modules if
807
+ // it shows up. This is due to various linker shenanigans that
808
+ // we'll encounter later.
809
+ let is_allocator = module_kind == ModuleKind :: Allocator ;
810
+
803
811
// We ignore a request for full crate graph LTO if the crate type
804
812
// is only an rlib, as there is no full crate graph to process,
805
813
// that'll happen later.
@@ -811,7 +819,7 @@ pub(crate) fn compute_per_cgu_lto_type(
811
819
let is_rlib = matches ! ( sess_crate_types, [ CrateType :: Rlib ] ) ;
812
820
813
821
match sess_lto {
814
- Lto :: ThinLocal if !linker_does_lto => ComputedLtoType :: Thin ,
822
+ Lto :: ThinLocal if !linker_does_lto && !is_allocator => ComputedLtoType :: Thin ,
815
823
Lto :: Thin if !linker_does_lto && !is_rlib => ComputedLtoType :: Thin ,
816
824
Lto :: Fat if !is_rlib => ComputedLtoType :: Fat ,
817
825
_ => ComputedLtoType :: No ,
@@ -825,18 +833,23 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
825
833
let dcx = cgcx. create_dcx ( ) ;
826
834
let dcx = dcx. handle ( ) ;
827
835
828
- B :: optimize ( cgcx, dcx, & mut module, & cgcx. module_config ) ;
836
+ let module_config = match module. kind {
837
+ ModuleKind :: Regular => & cgcx. module_config ,
838
+ ModuleKind :: Allocator => & cgcx. allocator_config ,
839
+ } ;
840
+
841
+ B :: optimize ( cgcx, dcx, & mut module, module_config) ;
829
842
830
843
// After we've done the initial round of optimizations we need to
831
844
// decide whether to synchronously codegen this module or ship it
832
845
// back to the coordinator thread for further LTO processing (which
833
846
// has to wait for all the initial modules to be optimized).
834
847
835
- let lto_type = compute_per_cgu_lto_type ( & cgcx. lto , & cgcx. opts , & cgcx. crate_types ) ;
848
+ let lto_type = compute_per_cgu_lto_type ( & cgcx. lto , & cgcx. opts , & cgcx. crate_types , module . kind ) ;
836
849
837
850
// If we're doing some form of incremental LTO then we need to be sure to
838
851
// save our module to disk first.
839
- let bitcode = if cgcx . module_config . emit_pre_lto_bc {
852
+ let bitcode = if module_config. emit_pre_lto_bc {
840
853
let filename = pre_lto_bitcode_filename ( & module. name ) ;
841
854
cgcx. incr_comp_session_dir . as_ref ( ) . map ( |path| path. join ( & filename) )
842
855
} else {
@@ -845,7 +858,7 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
845
858
846
859
match lto_type {
847
860
ComputedLtoType :: No => {
848
- let module = B :: codegen ( cgcx, module, & cgcx . module_config ) ;
861
+ let module = B :: codegen ( cgcx, module, module_config) ;
849
862
WorkItemResult :: Finished ( module)
850
863
}
851
864
ComputedLtoType :: Thin => {
@@ -1133,6 +1146,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
1133
1146
diag_emitter : shared_emitter. clone ( ) ,
1134
1147
output_filenames : Arc :: clone ( tcx. output_filenames ( ( ) ) ) ,
1135
1148
module_config : regular_config,
1149
+ allocator_config,
1136
1150
tm_factory : backend. target_machine_factory ( tcx. sess , ol, backend_features) ,
1137
1151
msvc_imps_needed : msvc_imps_needed ( tcx) ,
1138
1152
is_pe_coff : tcx. sess . target . is_like_windows ,
@@ -1147,11 +1161,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
1147
1161
invocation_temp : sess. invocation_temp . clone ( ) ,
1148
1162
} ;
1149
1163
1150
- let compiled_allocator_module = allocator_module. map ( |mut allocator_module| {
1151
- B :: optimize ( & cgcx, tcx. sess . dcx ( ) , & mut allocator_module, & allocator_config) ;
1152
- B :: codegen ( & cgcx, allocator_module, & allocator_config)
1153
- } ) ;
1154
-
1155
1164
// This is the "main loop" of parallel work happening for parallel codegen.
1156
1165
// It's here that we manage parallelism, schedule work, and work with
1157
1166
// messages coming from clients.
@@ -1331,6 +1340,17 @@ fn start_executing_work<B: ExtraBackendMethods>(
1331
1340
1332
1341
let mut llvm_start_time: Option < VerboseTimingGuard < ' _ > > = None ;
1333
1342
1343
+ let compiled_allocator_module = allocator_module. and_then ( |allocator_module| {
1344
+ match execute_optimize_work_item ( & cgcx, allocator_module) {
1345
+ WorkItemResult :: Finished ( compiled_module) => return Some ( compiled_module) ,
1346
+ WorkItemResult :: NeedsFatLto ( fat_lto_input) => needs_fat_lto. push ( fat_lto_input) ,
1347
+ WorkItemResult :: NeedsThinLto ( name, thin_buffer) => {
1348
+ needs_thin_lto. push ( ( name, thin_buffer) )
1349
+ }
1350
+ }
1351
+ None
1352
+ } ) ;
1353
+
1334
1354
// Run the message loop while there's still anything that needs message
1335
1355
// processing. Note that as soon as codegen is aborted we simply want to
1336
1356
// wait for all existing work to finish, so many of the conditions here
0 commit comments