Skip to content

Commit cca2388

Browse files
committed
lto: use the object crate to load bitcode sections
Upstream change llvm/llvm-project@6b539f5 changed `isSectionBitcode` works and it now only respects `.llvm.lto` sections instead of also `.llvmbc`, which it says was never intended to be used for LTO. We already have the object crate handy, so it's easy to use that to load the section. We have to sniff for raw bitcode files by hand, as `object` doesn't support those, but that's easy enough. I also look for both .llvmbc and .llvm.lto sections so that the behavior of the new code matches the old LLVM behavior exactly, though .llvm.lto sections seem to not (currently) be covered by tests. r? @nikic @rustbot label: +llvm-main
1 parent d8c69df commit cca2388

File tree

3 files changed

+18
-48
lines changed

3 files changed

+18
-48
lines changed

compiler/rustc_codegen_llvm/src/back/lto.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ use std::path::Path;
2828
use std::slice;
2929
use std::sync::Arc;
3030

31+
use object::Object;
32+
use object::ObjectSection;
33+
3134
/// We keep track of the computed LTO cache keys from the previous
3235
/// session to determine which CGUs we can reuse.
3336
pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin";
@@ -142,23 +145,21 @@ fn prepare_lto(
142145
}
143146

144147
fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], LtoBitcodeFromRlib> {
145-
let mut len = 0;
146-
let data =
147-
unsafe { llvm::LLVMRustGetBitcodeSliceFromObjectData(obj.as_ptr(), obj.len(), &mut len) };
148-
if !data.is_null() {
149-
assert!(len != 0);
150-
let bc = unsafe { slice::from_raw_parts(data, len) };
151-
152-
// `bc` must be a sub-slice of `obj`.
153-
assert!(obj.as_ptr() <= bc.as_ptr());
154-
assert!(bc[bc.len()..bc.len()].as_ptr() <= obj[obj.len()..obj.len()].as_ptr());
155-
156-
Ok(bc)
157-
} else {
158-
assert!(len == 0);
159-
Err(LtoBitcodeFromRlib {
160-
llvm_err: llvm::last_error().unwrap_or_else(|| "unknown LLVM error".to_string()),
161-
})
148+
// The object crate doesn't understand bitcode files, but we can just sniff for the possible
149+
// magic strings here and return the whole slice directly.
150+
if obj.starts_with(b"\xDE\xC0\x17\x0B") || obj.starts_with(b"BC\xC0\xDE") {
151+
return Ok(obj);
152+
}
153+
match object::read::File::parse(obj) {
154+
Ok(f) => match f.section_by_name(".llvmbc").or_else(|| f.section_by_name(".llvm.lto")) {
155+
Some(d) => Ok(d.data().unwrap()),
156+
None => Err(LtoBitcodeFromRlib {
157+
llvm_err: "Bitcode section not found in object file".to_string(),
158+
}),
159+
},
160+
Err(e) => {
161+
Err(LtoBitcodeFromRlib { llvm_err: format!("error loading bitcode section: {}", e) })
162+
}
162163
}
163164
}
164165

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2309,11 +2309,6 @@ extern "C" {
23092309
len: usize,
23102310
Identifier: *const c_char,
23112311
) -> Option<&Module>;
2312-
pub fn LLVMRustGetBitcodeSliceFromObjectData(
2313-
Data: *const u8,
2314-
len: usize,
2315-
out_len: &mut usize,
2316-
) -> *const u8;
23172312

23182313
pub fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>;
23192314
pub fn LLVMRustLinkerAdd(

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,32 +1481,6 @@ LLVMRustParseBitcodeForLTO(LLVMContextRef Context,
14811481
return wrap(std::move(*SrcOrError).release());
14821482
}
14831483

1484-
// Find the bitcode section in the object file data and return it as a slice.
1485-
// Fail if the bitcode section is present but empty.
1486-
//
1487-
// On success, the return value is the pointer to the start of the slice and
1488-
// `out_len` is filled with the (non-zero) length. On failure, the return value
1489-
// is `nullptr` and `out_len` is set to zero.
1490-
extern "C" const char*
1491-
LLVMRustGetBitcodeSliceFromObjectData(const char *data,
1492-
size_t len,
1493-
size_t *out_len) {
1494-
*out_len = 0;
1495-
1496-
StringRef Data(data, len);
1497-
MemoryBufferRef Buffer(Data, ""); // The id is unused.
1498-
1499-
Expected<MemoryBufferRef> BitcodeOrError =
1500-
object::IRObjectFile::findBitcodeInMemBuffer(Buffer);
1501-
if (!BitcodeOrError) {
1502-
LLVMRustSetLastError(toString(BitcodeOrError.takeError()).c_str());
1503-
return nullptr;
1504-
}
1505-
1506-
*out_len = BitcodeOrError->getBufferSize();
1507-
return BitcodeOrError->getBufferStart();
1508-
}
1509-
15101484
// Computes the LTO cache key for the provided 'ModId' in the given 'Data',
15111485
// storing the result in 'KeyOut'.
15121486
// Currently, this cache key is a SHA-1 hash of anything that could affect

0 commit comments

Comments
 (0)