@@ -45,10 +45,22 @@ pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
4545 }
4646}
4747
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+
4860fn prepare_lto (
4961 cgcx : & CodegenContext < LlvmCodegenBackend > ,
5062 dcx : & DiagCtxt ,
51- ) -> Result < ( Vec < CString > , Vec < ( SerializedModule < ModuleBuffer > , CString ) > ) , FatalError > {
63+ ) -> Result < ( Vec < CString > , Vec < SerializedModuleInfo > ) , FatalError > {
5264 let export_threshold = match cgcx. lto {
5365 // We're just doing LTO for our one crate
5466 Lto :: ThinLocal => SymbolExportLevel :: Rust ,
@@ -127,6 +139,7 @@ fn prepare_lto(
127139 } )
128140 } )
129141 . filter ( |& ( name, _) | looks_like_rust_object_file ( name) ) ;
142+ let compiler_builtins = cgcx. compiler_builtins == Some ( cnum) ;
130143 for ( name, child) in obj_files {
131144 info ! ( "adding bitcode from {}" , name) ;
132145 match get_bitcode_slice_from_object_data (
@@ -135,7 +148,11 @@ fn prepare_lto(
135148 ) {
136149 Ok ( data) => {
137150 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+ ) ) ;
139156 }
140157 Err ( e) => {
141158 dcx. emit_err ( e) ;
@@ -239,7 +256,7 @@ fn fat_lto(
239256 dcx : & DiagCtxt ,
240257 modules : Vec < FatLtoInput < LlvmCodegenBackend > > ,
241258 cached_modules : Vec < ( SerializedModule < ModuleBuffer > , WorkProduct ) > ,
242- mut serialized_modules : Vec < ( SerializedModule < ModuleBuffer > , CString ) > ,
259+ mut serialized_modules : Vec < SerializedModuleInfo > ,
243260 symbols_below_threshold : & [ * const libc:: c_char ] ,
244261) -> Result < LtoModuleCodegen < LlvmCodegenBackend > , FatalError > {
245262 let _timer = cgcx. prof . generic_activity ( "LLVM_fat_lto_build_monolithic_module" ) ;
@@ -258,15 +275,19 @@ fn fat_lto(
258275 let mut in_memory = Vec :: new ( ) ;
259276 serialized_modules. extend ( cached_modules. into_iter ( ) . map ( |( buffer, wp) | {
260277 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 )
262279 } ) ) ;
263280 for module in modules {
264281 match module {
265282 FatLtoInput :: InMemory ( m) => in_memory. push ( m) ,
266283 FatLtoInput :: Serialized { name, buffer } => {
267284 info ! ( "pushing serialized module {:?}" , name) ;
268285 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+ ) ) ;
270291 }
271292 }
272293 }
@@ -299,10 +320,10 @@ fn fat_lto(
299320 Some ( ( _cost, i) ) => in_memory. remove ( i) ,
300321 None => {
301322 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 ) ;
303324 info ! ( "no in-memory regular modules to choose from, parsing {:?}" , name) ;
304325 ModuleCodegen {
305- module_llvm : ModuleLlvm :: parse ( cgcx, & name, buffer . data ( ) , dcx) ?,
326+ module_llvm : ModuleLlvm :: parse ( cgcx, & name, module . data ( ) , dcx) ?,
306327 name : name. into_string ( ) . unwrap ( ) ,
307328 kind : ModuleKind :: Regular ,
308329 }
@@ -330,26 +351,39 @@ fn fat_lto(
330351 for module in in_memory {
331352 let buffer = ModuleBuffer :: new ( module. module_llvm . llmod ( ) ) ;
332353 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+ ) ) ;
334359 }
335360 // 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+ } ) ;
337370
338371 // For all serialized bitcode files we parse them and link them in as we did
339372 // above, this is all mostly handled in C++. Like above, though, we don't
340373 // know much about the memory management here so we err on the side of being
341374 // save and persist everything with the original module.
342375 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;
344378 let _timer = cgcx
345379 . prof
346380 . generic_activity_with_arg_recorder ( "LLVM_fat_lto_link_module" , |recorder| {
347381 recorder. record_arg ( format ! ( "{name:?}" ) )
348382 } ) ;
349383 info ! ( "linking {:?}" , name) ;
350- let data = bc_decoded . data ( ) ;
384+ let data = module . data ( ) ;
351385 linker. add ( data) . map_err ( |( ) | write:: llvm_err ( dcx, LlvmError :: LoadBitcode { name } ) ) ?;
352- serialized_bitcode. push ( bc_decoded ) ;
386+ serialized_bitcode. push ( module ) ;
353387 }
354388 drop ( linker) ;
355389 save_temp_bitcode ( cgcx, & module, "lto.input" ) ;
@@ -433,7 +467,7 @@ fn thin_lto(
433467 cgcx : & CodegenContext < LlvmCodegenBackend > ,
434468 dcx : & DiagCtxt ,
435469 modules : Vec < ( String , ThinBuffer ) > ,
436- serialized_modules : Vec < ( SerializedModule < ModuleBuffer > , CString ) > ,
470+ serialized_modules : Vec < SerializedModuleInfo > ,
437471 cached_modules : Vec < ( SerializedModule < ModuleBuffer > , WorkProduct ) > ,
438472 symbols_below_threshold : & [ * const libc:: c_char ] ,
439473) -> Result < ( Vec < LtoModuleCodegen < LlvmCodegenBackend > > , Vec < WorkProduct > ) , FatalError > {
@@ -479,10 +513,12 @@ fn thin_lto(
479513 // we must always unconditionally look at the index).
480514 let mut serialized = Vec :: with_capacity ( serialized_modules. len ( ) + cached_modules. len ( ) ) ;
481515
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+ } ) ;
484519
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;
486522 info ! ( "upstream or cached module {:?}" , name) ;
487523 thin_modules. push ( llvm:: ThinLTOModule {
488524 identifier : name. as_ptr ( ) ,
0 commit comments