Skip to content

Commit 53eed7c

Browse files
committed
Avoid copying the bitcode out of rlibs
Instead keep it as part of the mmap.
1 parent e108534 commit 53eed7c

File tree

1 file changed

+26
-18
lines changed
  • compiler/rustc_codegen_llvm/src/back

1 file changed

+26
-18
lines changed

compiler/rustc_codegen_llvm/src/back/lto.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_codegen_ssa::traits::*;
1414
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
1515
use rustc_data_structures::fx::FxHashMap;
1616
use rustc_data_structures::memmap::Mmap;
17-
use rustc_data_structures::owned_slice::slice_owned;
17+
use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
1818
use rustc_errors::DiagCtxtHandle;
1919
use rustc_middle::bug;
2020
use rustc_middle::dep_graph::WorkProduct;
@@ -57,10 +57,13 @@ fn prepare_lto(
5757
let mut upstream_modules = Vec::new();
5858
if cgcx.lto != Lto::ThinLocal {
5959
for path in each_linked_rlib_for_lto {
60-
let archive_data = unsafe {
61-
Mmap::map(std::fs::File::open(&path).expect("couldn't open rlib"))
62-
.expect("couldn't map rlib")
63-
};
60+
let archive_data = slice_owned(
61+
unsafe {
62+
Mmap::map(std::fs::File::open(&path).expect("couldn't open rlib"))
63+
.expect("couldn't map rlib")
64+
},
65+
|data| &*data,
66+
);
6467
let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib");
6568
let obj_files = archive
6669
.members()
@@ -72,13 +75,14 @@ fn prepare_lto(
7275
.filter(|&(name, _)| looks_like_rust_object_file(name));
7376
for (name, child) in obj_files {
7477
info!("adding bitcode from {}", name);
75-
match get_bitcode_slice_from_object_data(
76-
child.data(&*archive_data).expect("corrupt rlib"),
77-
cgcx,
78-
) {
78+
let (offset, size) = child.file_range();
79+
let child_data = archive_data.clone().slice(|data| {
80+
data.get(offset as usize..offset as usize + size as usize)
81+
.expect("corrupt rlib")
82+
});
83+
match get_bitcode_slice_from_object_data(child_data, cgcx) {
7984
Ok(data) => {
80-
let module =
81-
SerializedModule::FromFile(slice_owned(data.to_vec(), |data| &*data));
85+
let module = SerializedModule::FromFile(data);
8286
upstream_modules.push((module, CString::new(name).unwrap()));
8387
}
8488
Err(e) => dcx.emit_fatal(e),
@@ -90,29 +94,33 @@ fn prepare_lto(
9094
(symbols_below_threshold, upstream_modules)
9195
}
9296

93-
fn get_bitcode_slice_from_object_data<'a>(
94-
obj: &'a [u8],
97+
fn get_bitcode_slice_from_object_data(
98+
data: OwnedSlice,
9599
cgcx: &CodegenContext<LlvmCodegenBackend>,
96-
) -> Result<&'a [u8], LtoBitcodeFromRlib> {
100+
) -> Result<OwnedSlice, LtoBitcodeFromRlib> {
97101
// We're about to assume the data here is an object file with sections, but if it's raw LLVM IR
98102
// that won't work. Fortunately, if that's what we have we can just return the object directly,
99103
// so we sniff the relevant magic strings here and return.
100-
if obj.starts_with(b"\xDE\xC0\x17\x0B") || obj.starts_with(b"BC\xC0\xDE") {
101-
return Ok(obj);
104+
if data.starts_with(b"\xDE\xC0\x17\x0B") || data.starts_with(b"BC\xC0\xDE") {
105+
return Ok(data);
102106
}
103107
// We drop the "__LLVM," prefix here because on Apple platforms there's a notion of "segment
104108
// name" which in the public API for sections gets treated as part of the section name, but
105109
// internally in MachOObjectFile.cpp gets treated separately.
106110
let section_name = bitcode_section_name(cgcx).to_str().unwrap().trim_start_matches("__LLVM,");
107111

108112
let obj =
109-
object::File::parse(obj).map_err(|err| LtoBitcodeFromRlib { err: err.to_string() })?;
113+
object::File::parse(&*data).map_err(|err| LtoBitcodeFromRlib { err: err.to_string() })?;
110114

111115
let section = obj
112116
.section_by_name(section_name)
113117
.ok_or_else(|| LtoBitcodeFromRlib { err: format!("Can't find section {section_name}") })?;
114118

115-
section.data().map_err(|err| LtoBitcodeFromRlib { err: err.to_string() })
119+
if let Some((offset, size)) = section.file_range() {
120+
Ok(data.slice(|data| &data[offset as usize..offset as usize + size as usize]))
121+
} else {
122+
Err(LtoBitcodeFromRlib { err: format!("Section {section_name} doesn't have contents") })
123+
}
116124
}
117125

118126
/// Performs fat LTO by merging all modules into a single one and returning it

0 commit comments

Comments
 (0)