Skip to content

Commit c6b2967

Browse files
committed
When performing FatLTO, place compiler_builtins at the end
Place compiler_builtins at the end. After that we check if any crate wants to customize the builtin functions. Remove the function of compiler_builtins, if any.
1 parent 05b66a9 commit c6b2967

File tree

2 files changed

+54
-16
lines changed
  • compiler

2 files changed

+54
-16
lines changed

compiler/rustc_codegen_llvm/src/back/lto.rs

+52-16
Original file line numberDiff line numberDiff line change
@@ -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+
4860
fn 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(),

compiler/rustc_codegen_ssa/src/back/write.rs

+2
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
326326
pub opts: Arc<config::Options>,
327327
pub crate_types: Vec<CrateType>,
328328
pub each_linked_rlib_for_lto: Vec<(CrateNum, PathBuf)>,
329+
pub compiler_builtins: Option<CrateNum>,
329330
pub output_filenames: Arc<OutputFilenames>,
330331
pub regular_module_config: Arc<ModuleConfig>,
331332
pub metadata_module_config: Arc<ModuleConfig>,
@@ -1089,6 +1090,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
10891090
let cgcx = CodegenContext::<B> {
10901091
crate_types: tcx.crate_types().to_vec(),
10911092
each_linked_rlib_for_lto,
1093+
compiler_builtins: crate_info.compiler_builtins,
10921094
lto: sess.lto(),
10931095
fewer_names: sess.fewer_names(),
10941096
save_temps: sess.opts.cg.save_temps,

0 commit comments

Comments
 (0)