Rollup merge of #125345 - durin42:thin-link-bitcode, r=bjorn3
rustc_codegen_llvm: add support for writing summary bitcode Typical uses of ThinLTO don't have any use for this as a standalone file, but distributed ThinLTO uses this to make the linker phase more efficient. With clang you'd do something like `clang -flto=thin -fthin-link-bitcode=foo.indexing.o -c foo.c` and then get both foo.o (full of bitcode) and foo.indexing.o (just the summary or index part of the bitcode). That's then usable by a two-stage linking process that's more friendly to distributed build systems like bazel, which is why I'm working on this area. I talked some to `@teresajohnson` about naming in this area, as things seem to be a little confused between various blog posts and build systems. "bitcode index" and "bitcode summary" tend to be a little too ambiguous, and she tends to use "thin link bitcode" and "minimized bitcode" (which matches the descriptions in LLVM). Since the clang option is thin-link-bitcode, I went with that to try and not add a new spelling in the world. Per `@dtolnay,` you can work around the lack of this by using `lld --thinlto-index-only` to do the indexing on regular .o files of bitcode, but that is a bit wasteful on actions when we already have all the information in rustc and could just write out the matching minimized bitcode. I didn't test that at all in our infrastructure, because by the time I learned that I already had this patch largely written.
This commit is contained in:
commit
4ee97fc3db
10 changed files with 107 additions and 18 deletions
|
@ -229,9 +229,12 @@ pub(crate) fn run_thin(
|
|||
thin_lto(cgcx, &dcx, modules, upstream_modules, cached_modules, &symbols_below_threshold)
|
||||
}
|
||||
|
||||
pub(crate) fn prepare_thin(module: ModuleCodegen<ModuleLlvm>) -> (String, ThinBuffer) {
|
||||
pub(crate) fn prepare_thin(
|
||||
module: ModuleCodegen<ModuleLlvm>,
|
||||
emit_summary: bool,
|
||||
) -> (String, ThinBuffer) {
|
||||
let name = module.name;
|
||||
let buffer = ThinBuffer::new(module.module_llvm.llmod(), true);
|
||||
let buffer = ThinBuffer::new(module.module_llvm.llmod(), true, emit_summary);
|
||||
(name, buffer)
|
||||
}
|
||||
|
||||
|
@ -671,9 +674,9 @@ unsafe impl Send for ThinBuffer {}
|
|||
unsafe impl Sync for ThinBuffer {}
|
||||
|
||||
impl ThinBuffer {
|
||||
pub fn new(m: &llvm::Module, is_thin: bool) -> ThinBuffer {
|
||||
pub fn new(m: &llvm::Module, is_thin: bool, emit_summary: bool) -> ThinBuffer {
|
||||
unsafe {
|
||||
let buffer = llvm::LLVMRustThinLTOBufferCreate(m, is_thin);
|
||||
let buffer = llvm::LLVMRustThinLTOBufferCreate(m, is_thin, emit_summary);
|
||||
ThinBuffer(buffer)
|
||||
}
|
||||
}
|
||||
|
@ -687,6 +690,14 @@ impl ThinBufferMethods for ThinBuffer {
|
|||
slice::from_raw_parts(ptr, len)
|
||||
}
|
||||
}
|
||||
|
||||
fn thin_link_data(&self) -> &[u8] {
|
||||
unsafe {
|
||||
let ptr = llvm::LLVMRustThinLTOBufferThinLinkDataPtr(self.0) as *const _;
|
||||
let len = llvm::LLVMRustThinLTOBufferThinLinkDataLen(self.0);
|
||||
slice::from_raw_parts(ptr, len)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ThinBuffer {
|
||||
|
|
|
@ -708,13 +708,15 @@ pub(crate) unsafe fn codegen(
|
|||
// asm from LLVM and use `gcc` to create the object file.
|
||||
|
||||
let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
|
||||
let bc_summary_out =
|
||||
cgcx.output_filenames.temp_path(OutputType::ThinLinkBitcode, module_name);
|
||||
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
|
||||
|
||||
if config.bitcode_needed() {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &*module.name);
|
||||
let thin = ThinBuffer::new(llmod, config.emit_thin_lto);
|
||||
let thin = ThinBuffer::new(llmod, config.emit_thin_lto, config.emit_thin_lto_summary);
|
||||
let data = thin.data();
|
||||
|
||||
if let Some(bitcode_filename) = bc_out.file_name() {
|
||||
|
@ -725,6 +727,25 @@ pub(crate) unsafe fn codegen(
|
|||
);
|
||||
}
|
||||
|
||||
if config.emit_thin_lto_summary
|
||||
&& let Some(thin_link_bitcode_filename) = bc_summary_out.file_name()
|
||||
{
|
||||
let summary_data = thin.thin_link_data();
|
||||
cgcx.prof.artifact_size(
|
||||
"llvm_bitcode_summary",
|
||||
thin_link_bitcode_filename.to_string_lossy(),
|
||||
summary_data.len() as u64,
|
||||
);
|
||||
|
||||
let _timer = cgcx.prof.generic_activity_with_arg(
|
||||
"LLVM_module_codegen_emit_bitcode_summary",
|
||||
&*module.name,
|
||||
);
|
||||
if let Err(err) = fs::write(&bc_summary_out, summary_data) {
|
||||
dcx.emit_err(WriteBytecode { path: &bc_summary_out, err });
|
||||
}
|
||||
}
|
||||
|
||||
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
|
|
|
@ -240,8 +240,11 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
|||
) -> Result<CompiledModule, FatalError> {
|
||||
back::write::codegen(cgcx, dcx, module, config)
|
||||
}
|
||||
fn prepare_thin(module: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer) {
|
||||
back::lto::prepare_thin(module)
|
||||
fn prepare_thin(
|
||||
module: ModuleCodegen<Self::Module>,
|
||||
emit_summary: bool,
|
||||
) -> (String, Self::ThinBuffer) {
|
||||
back::lto::prepare_thin(module, emit_summary)
|
||||
}
|
||||
fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) {
|
||||
(module.name, back::lto::ModuleBuffer::new(module.module_llvm.llmod()))
|
||||
|
|
|
@ -2350,10 +2350,16 @@ extern "C" {
|
|||
#[allow(improper_ctypes)]
|
||||
pub fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString);
|
||||
|
||||
pub fn LLVMRustThinLTOBufferCreate(M: &Module, is_thin: bool) -> &'static mut ThinLTOBuffer;
|
||||
pub fn LLVMRustThinLTOBufferCreate(
|
||||
M: &Module,
|
||||
is_thin: bool,
|
||||
emit_summary: bool,
|
||||
) -> &'static mut ThinLTOBuffer;
|
||||
pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);
|
||||
pub fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char;
|
||||
pub fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t;
|
||||
pub fn LLVMRustThinLTOBufferThinLinkDataPtr(M: &ThinLTOBuffer) -> *const c_char;
|
||||
pub fn LLVMRustThinLTOBufferThinLinkDataLen(M: &ThinLTOBuffer) -> size_t;
|
||||
pub fn LLVMRustCreateThinLTOData(
|
||||
Modules: *const ThinLTOModule,
|
||||
NumModules: c_uint,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue