@@ -45,10 +45,22 @@ pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
45
45
}
46
46
}
47
47
48
+ struct SerializedModuleInfo {
49
+ module : SerializedModule < ModuleBuffer > ,
50
+ name : CString ,
51
+ compiler_builtins : bool ,
52
+ }
53
+
54
+ impl SerializedModuleInfo {
55
+ fn new ( module : SerializedModule < ModuleBuffer > , name : CString , compiler_builtins : bool ) -> Self {
56
+ Self { module, name, compiler_builtins }
57
+ }
58
+ }
59
+
48
60
fn prepare_lto (
49
61
cgcx : & CodegenContext < LlvmCodegenBackend > ,
50
62
dcx : & DiagCtxt ,
51
- ) -> Result < ( Vec < CString > , Vec < ( SerializedModule < ModuleBuffer > , CString ) > ) , FatalError > {
63
+ ) -> Result < ( Vec < CString > , Vec < SerializedModuleInfo > ) , FatalError > {
52
64
let export_threshold = match cgcx. lto {
53
65
// We're just doing LTO for our one crate
54
66
Lto :: ThinLocal => SymbolExportLevel :: Rust ,
@@ -127,6 +139,7 @@ fn prepare_lto(
127
139
} )
128
140
} )
129
141
. filter ( |& ( name, _) | looks_like_rust_object_file ( name) ) ;
142
+ let compiler_builtins = cgcx. compiler_builtins == Some ( cnum) ;
130
143
for ( name, child) in obj_files {
131
144
info ! ( "adding bitcode from {}" , name) ;
132
145
match get_bitcode_slice_from_object_data (
@@ -135,7 +148,11 @@ fn prepare_lto(
135
148
) {
136
149
Ok ( data) => {
137
150
let module = SerializedModule :: FromRlib ( data. to_vec ( ) ) ;
138
- upstream_modules. push ( ( module, CString :: new ( name) . unwrap ( ) ) ) ;
151
+ upstream_modules. push ( SerializedModuleInfo :: new (
152
+ module,
153
+ CString :: new ( name) . unwrap ( ) ,
154
+ compiler_builtins,
155
+ ) ) ;
139
156
}
140
157
Err ( e) => {
141
158
dcx. emit_err ( e) ;
@@ -239,7 +256,7 @@ fn fat_lto(
239
256
dcx : & DiagCtxt ,
240
257
modules : Vec < FatLtoInput < LlvmCodegenBackend > > ,
241
258
cached_modules : Vec < ( SerializedModule < ModuleBuffer > , WorkProduct ) > ,
242
- mut serialized_modules : Vec < ( SerializedModule < ModuleBuffer > , CString ) > ,
259
+ mut serialized_modules : Vec < SerializedModuleInfo > ,
243
260
symbols_below_threshold : & [ * const libc:: c_char ] ,
244
261
) -> Result < LtoModuleCodegen < LlvmCodegenBackend > , FatalError > {
245
262
let _timer = cgcx. prof . generic_activity ( "LLVM_fat_lto_build_monolithic_module" ) ;
@@ -258,15 +275,19 @@ fn fat_lto(
258
275
let mut in_memory = Vec :: new ( ) ;
259
276
serialized_modules. extend ( cached_modules. into_iter ( ) . map ( |( buffer, wp) | {
260
277
info ! ( "pushing cached module {:?}" , wp. cgu_name) ;
261
- ( buffer, CString :: new ( wp. cgu_name ) . unwrap ( ) )
278
+ SerializedModuleInfo :: new ( buffer, CString :: new ( wp. cgu_name ) . unwrap ( ) , false )
262
279
} ) ) ;
263
280
for module in modules {
264
281
match module {
265
282
FatLtoInput :: InMemory ( m) => in_memory. push ( m) ,
266
283
FatLtoInput :: Serialized { name, buffer } => {
267
284
info ! ( "pushing serialized module {:?}" , name) ;
268
285
let buffer = SerializedModule :: Local ( buffer) ;
269
- serialized_modules. push ( ( buffer, CString :: new ( name) . unwrap ( ) ) ) ;
286
+ serialized_modules. push ( SerializedModuleInfo :: new (
287
+ buffer,
288
+ CString :: new ( name) . unwrap ( ) ,
289
+ false ,
290
+ ) ) ;
270
291
}
271
292
}
272
293
}
@@ -299,10 +320,10 @@ fn fat_lto(
299
320
Some ( ( _cost, i) ) => in_memory. remove ( i) ,
300
321
None => {
301
322
assert ! ( !serialized_modules. is_empty( ) , "must have at least one serialized module" ) ;
302
- let ( buffer , name) = serialized_modules. remove ( 0 ) ;
323
+ let SerializedModuleInfo { module , name, .. } = serialized_modules. remove ( 0 ) ;
303
324
info ! ( "no in-memory regular modules to choose from, parsing {:?}" , name) ;
304
325
ModuleCodegen {
305
- module_llvm : ModuleLlvm :: parse ( cgcx, & name, buffer . data ( ) , dcx) ?,
326
+ module_llvm : ModuleLlvm :: parse ( cgcx, & name, module . data ( ) , dcx) ?,
306
327
name : name. into_string ( ) . unwrap ( ) ,
307
328
kind : ModuleKind :: Regular ,
308
329
}
@@ -330,26 +351,39 @@ fn fat_lto(
330
351
for module in in_memory {
331
352
let buffer = ModuleBuffer :: new ( module. module_llvm . llmod ( ) ) ;
332
353
let llmod_id = CString :: new ( & module. name [ ..] ) . unwrap ( ) ;
333
- serialized_modules. push ( ( SerializedModule :: Local ( buffer) , llmod_id) ) ;
354
+ serialized_modules. push ( SerializedModuleInfo :: new (
355
+ SerializedModule :: Local ( buffer) ,
356
+ llmod_id,
357
+ false ,
358
+ ) ) ;
334
359
}
335
360
// Sort the modules to ensure we produce deterministic results.
336
- serialized_modules. sort_by ( |module1, module2| module1. 1 . cmp ( & module2. 1 ) ) ;
361
+ // Place compiler_builtins at the end. After that we check if any crate wants to
362
+ // customize the builtin functions. Remove the function of compiler_builtins, if any.
363
+ serialized_modules. sort_by ( |module1, module2| {
364
+ let compiler_builtins_cmp = module1. compiler_builtins . cmp ( & module2. compiler_builtins ) ;
365
+ if compiler_builtins_cmp. is_ne ( ) {
366
+ return compiler_builtins_cmp;
367
+ }
368
+ module1. name . cmp ( & module2. name )
369
+ } ) ;
337
370
338
371
// For all serialized bitcode files we parse them and link them in as we did
339
372
// above, this is all mostly handled in C++. Like above, though, we don't
340
373
// know much about the memory management here so we err on the side of being
341
374
// save and persist everything with the original module.
342
375
let mut linker = Linker :: new ( llmod) ;
343
- for ( bc_decoded, name) in serialized_modules {
376
+ for serialized_module in serialized_modules {
377
+ let SerializedModuleInfo { module, name, .. } = serialized_module;
344
378
let _timer = cgcx
345
379
. prof
346
380
. generic_activity_with_arg_recorder ( "LLVM_fat_lto_link_module" , |recorder| {
347
381
recorder. record_arg ( format ! ( "{name:?}" ) )
348
382
} ) ;
349
383
info ! ( "linking {:?}" , name) ;
350
- let data = bc_decoded . data ( ) ;
384
+ let data = module . data ( ) ;
351
385
linker. add ( data) . map_err ( |( ) | write:: llvm_err ( dcx, LlvmError :: LoadBitcode { name } ) ) ?;
352
- serialized_bitcode. push ( bc_decoded ) ;
386
+ serialized_bitcode. push ( module ) ;
353
387
}
354
388
drop ( linker) ;
355
389
save_temp_bitcode ( cgcx, & module, "lto.input" ) ;
@@ -433,7 +467,7 @@ fn thin_lto(
433
467
cgcx : & CodegenContext < LlvmCodegenBackend > ,
434
468
dcx : & DiagCtxt ,
435
469
modules : Vec < ( String , ThinBuffer ) > ,
436
- serialized_modules : Vec < ( SerializedModule < ModuleBuffer > , CString ) > ,
470
+ serialized_modules : Vec < SerializedModuleInfo > ,
437
471
cached_modules : Vec < ( SerializedModule < ModuleBuffer > , WorkProduct ) > ,
438
472
symbols_below_threshold : & [ * const libc:: c_char ] ,
439
473
) -> Result < ( Vec < LtoModuleCodegen < LlvmCodegenBackend > > , Vec < WorkProduct > ) , FatalError > {
@@ -479,10 +513,12 @@ fn thin_lto(
479
513
// we must always unconditionally look at the index).
480
514
let mut serialized = Vec :: with_capacity ( serialized_modules. len ( ) + cached_modules. len ( ) ) ;
481
515
482
- let cached_modules =
483
- cached_modules. into_iter ( ) . map ( |( sm, wp) | ( sm, CString :: new ( wp. cgu_name ) . unwrap ( ) ) ) ;
516
+ let cached_modules = cached_modules. into_iter ( ) . map ( |( sm, wp) | {
517
+ SerializedModuleInfo :: new ( sm, CString :: new ( wp. cgu_name ) . unwrap ( ) , false )
518
+ } ) ;
484
519
485
- for ( module, name) in serialized_modules. into_iter ( ) . chain ( cached_modules) {
520
+ for serialized_module in serialized_modules. into_iter ( ) . chain ( cached_modules) {
521
+ let SerializedModuleInfo { module, name, .. } = serialized_module;
486
522
info ! ( "upstream or cached module {:?}" , name) ;
487
523
thin_modules. push ( llvm:: ThinLTOModule {
488
524
identifier : name. as_ptr ( ) ,
0 commit comments