Auto merge of #115641 - durin42:llvm-18-fatlto-take-2, r=nikic

lto: load bitcode sections by name

Upstream change
llvm/llvm-project@6b539f5eb8 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 instead load sections by name, and sniff for raw bitcode by hand.

This is an alternative approach to #115136, where we tried the same thing using the `object` crate, but it got too fraught to continue.

r? `@nikic`
`@rustbot` label: +llvm-main
This commit is contained in:
bors 2023-09-08 19:07:17 +00:00
commit ffc48e3eda
4 changed files with 89 additions and 16 deletions

View file

@ -1,4 +1,6 @@
use crate::back::write::{self, save_temp_bitcode, CodegenDiagnosticsStage, DiagnosticHandlers};
use crate::back::write::{
self, bitcode_section_name, save_temp_bitcode, CodegenDiagnosticsStage, DiagnosticHandlers,
};
use crate::errors::{
DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib,
};
@ -120,6 +122,7 @@ fn prepare_lto(
info!("adding bitcode from {}", name);
match get_bitcode_slice_from_object_data(
child.data(&*archive_data).expect("corrupt rlib"),
cgcx,
) {
Ok(data) => {
let module = SerializedModule::FromRlib(data.to_vec());
@ -141,10 +144,29 @@ fn prepare_lto(
Ok((symbols_below_threshold, upstream_modules))
}
fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], LtoBitcodeFromRlib> {
fn get_bitcode_slice_from_object_data<'a>(
obj: &'a [u8],
cgcx: &CodegenContext<LlvmCodegenBackend>,
) -> Result<&'a [u8], LtoBitcodeFromRlib> {
// We're about to assume the data here is an object file with sections, but if it's raw LLVM IR that
// won't work. Fortunately, if that's what we have we can just return the object directly, so we sniff
// the relevant magic strings here and return.
if obj.starts_with(b"\xDE\xC0\x17\x0B") || obj.starts_with(b"BC\xC0\xDE") {
return Ok(obj);
}
// We drop the "__LLVM," prefix here because on Apple platforms there's a notion of "segment name"
// which in the public API for sections gets treated as part of the section name, but internally
// in MachOObjectFile.cpp gets treated separately.
let section_name = bitcode_section_name(cgcx).trim_start_matches("__LLVM,");
let mut len = 0;
let data =
unsafe { llvm::LLVMRustGetBitcodeSliceFromObjectData(obj.as_ptr(), obj.len(), &mut len) };
let data = unsafe {
llvm::LLVMRustGetSliceFromObjectDataByName(
obj.as_ptr(),
obj.len(),
section_name.as_ptr(),
&mut len,
)
};
if !data.is_null() {
assert!(len != 0);
let bc = unsafe { slice::from_raw_parts(data, len) };

View file

@ -873,6 +873,27 @@ fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data:
asm
}
fn target_is_apple(cgcx: &CodegenContext<LlvmCodegenBackend>) -> bool {
cgcx.opts.target_triple.triple().contains("-ios")
|| cgcx.opts.target_triple.triple().contains("-darwin")
|| cgcx.opts.target_triple.triple().contains("-tvos")
|| cgcx.opts.target_triple.triple().contains("-watchos")
}
fn target_is_aix(cgcx: &CodegenContext<LlvmCodegenBackend>) -> bool {
cgcx.opts.target_triple.triple().contains("-aix")
}
pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) -> &'static str {
if target_is_apple(cgcx) {
"__LLVM,__bitcode\0"
} else if target_is_aix(cgcx) {
".ipa\0"
} else {
".llvmbc\0"
}
}
/// Embed the bitcode of an LLVM module in the LLVM module itself.
///
/// This is done primarily for iOS where it appears to be standard to compile C
@ -933,11 +954,8 @@ unsafe fn embed_bitcode(
// Unfortunately, LLVM provides no way to set custom section flags. For ELF
// and COFF we emit the sections using module level inline assembly for that
// reason (see issue #90326 for historical background).
let is_aix = cgcx.opts.target_triple.triple().contains("-aix");
let is_apple = cgcx.opts.target_triple.triple().contains("-ios")
|| cgcx.opts.target_triple.triple().contains("-darwin")
|| cgcx.opts.target_triple.triple().contains("-tvos")
|| cgcx.opts.target_triple.triple().contains("-watchos");
let is_aix = target_is_aix(cgcx);
let is_apple = target_is_apple(cgcx);
if is_apple
|| is_aix
|| cgcx.opts.target_triple.triple().starts_with("wasm")
@ -952,13 +970,7 @@ unsafe fn embed_bitcode(
);
llvm::LLVMSetInitializer(llglobal, llconst);
let section = if is_apple {
"__LLVM,__bitcode\0"
} else if is_aix {
".ipa\0"
} else {
".llvmbc\0"
};
let section = bitcode_section_name(cgcx);
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);

View file

@ -2322,6 +2322,12 @@ extern "C" {
len: usize,
out_len: &mut usize,
) -> *const u8;
pub fn LLVMRustGetSliceFromObjectDataByName(
data: *const u8,
len: usize,
name: *const u8,
out_len: &mut usize,
) -> *const u8;
pub fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>;
pub fn LLVMRustLinkerAdd(