From 78516704f0fd5a16532017473358f3a2b438e90e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 31 Mar 2020 13:19:28 +1100 Subject: [PATCH 1/8] Remove `BitcodeSection::Marker`. It existed to minimize compile time of debug builds, but the subsequent commits in #70458 and corresponding changes to Cargo mean that bitcode will be omitted in most cases anyway. As a result, we just embed full bitcode whenever embedded bitcode is necessary. This commit also removes `BitcodeSection`, using just a `bool` instead now to indicate the presence of bitcode in an object file. --- src/librustc_codegen_llvm/back/write.rs | 34 ++++++++++--------------- src/librustc_codegen_ssa/back/write.rs | 27 +++----------------- 2 files changed, 18 insertions(+), 43 deletions(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 5708cb4e65418..378263f2adabb 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -14,7 +14,7 @@ use crate::type_::Type; use crate::LlvmCodegenBackend; use crate::ModuleLlvm; use log::debug; -use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig}; +use rustc_codegen_ssa::back::write::{CodegenContext, EmitObj, ModuleConfig}; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, RLIB_BYTECODE_EXTENSION}; use rustc_data_structures::small_c_str::SmallCStr; @@ -662,12 +662,12 @@ pub(crate) unsafe fn codegen( } } - if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) { + if config.emit_obj == (EmitObj::ObjectCode { bitcode_section: true }) { let _timer = cgcx.prof.generic_activity_with_arg( "LLVM_module_codegen_embed_bitcode", &module.name[..], ); - embed_bitcode(cgcx, llcx, llmod, Some(data)); + embed_bitcode(cgcx, llcx, llmod, data); } if config.emit_bc_compressed { @@ -682,8 +682,6 @@ pub(crate) unsafe fn codegen( diag_handler.err(&msg); } } - } else if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Marker) { - embed_bitcode(cgcx, llcx, llmod, None); } if config.emit_ir { @@ -742,7 +740,7 @@ pub(crate) unsafe fn codegen( // because that triggers various errors like invalid IR or broken // binaries. So we must clone the module to produce the asm output // if we are also producing object code. - let llmod = if let EmitObj::ObjectCode(_) = config.emit_obj { + let llmod = if let EmitObj::ObjectCode { .. } = config.emit_obj { llvm::LLVMCloneModule(llmod) } else { llmod @@ -753,7 +751,7 @@ pub(crate) unsafe fn codegen( } match config.emit_obj { - EmitObj::ObjectCode(_) => { + EmitObj::ObjectCode { .. } => { let _timer = cgcx .prof .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]); @@ -799,29 +797,25 @@ pub(crate) unsafe fn codegen( /// 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 -/// code at least with `-fembed-bitcode` which creates two sections in the -/// executable: +/// This is much like compiling C code with `-fembed-bitcode` which creates two +/// sections in the executable: /// /// * __LLVM,__bitcode /// * __LLVM,__cmdline /// -/// It appears *both* of these sections are necessary to get the linker to -/// recognize what's going on. For us though we just always throw in an empty -/// cmdline section. +/// On iOS it appears *both* of these sections are necessary to get the linker +/// to recognize what's going on. For us though we just always throw in an +/// empty cmdline section. /// -/// Furthermore debug/O1 builds don't actually embed bitcode but rather just -/// embed an empty section. -/// -/// Basically all of this is us attempting to follow in the footsteps of clang -/// on iOS. See #35968 for lots more info. +/// This started with us attempting to follow in the footsteps of clang on iOS +/// (see #35968 for lots more info) but it is now used for all targets. unsafe fn embed_bitcode( cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module, - bitcode: Option<&[u8]>, + bitcode: &[u8], ) { - let llconst = common::bytes_in_context(llcx, bitcode.unwrap_or(&[])); + let llconst = common::bytes_in_context(llcx, bitcode); let llglobal = llvm::LLVMAddGlobal( llmod, common::val_ty(llconst), diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index b1fb1ef0e331c..0df9373a2618f 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -61,21 +61,7 @@ pub enum EmitObj { Bitcode, // Object code, possibly augmented with a bitcode section. - ObjectCode(BitcodeSection), -} - -/// What kind of llvm bitcode section to embed in an object file. -#[derive(Clone, Copy, PartialEq)] -pub enum BitcodeSection { - // No bitcode section. - None, - - // An empty bitcode section (to placate tools such as the iOS linker that - // require this section even if they don't use it). - Marker, - - // A full, uncompressed bitcode section. - Full, + ObjectCode { bitcode_section: bool }, } /// Module-specific configuration for `optimize_and_codegen`. @@ -146,14 +132,9 @@ impl ModuleConfig { { EmitObj::Bitcode } else if sess.opts.debugging_opts.embed_bitcode { - match sess.opts.optimize { - config::OptLevel::No | config::OptLevel::Less => { - EmitObj::ObjectCode(BitcodeSection::Marker) - } - _ => EmitObj::ObjectCode(BitcodeSection::Full), - } + EmitObj::ObjectCode { bitcode_section: true } } else { - EmitObj::ObjectCode(BitcodeSection::None) + EmitObj::ObjectCode { bitcode_section: false } }; ModuleConfig { @@ -263,7 +244,7 @@ impl ModuleConfig { self.emit_bc || self.emit_bc_compressed || self.emit_obj == EmitObj::Bitcode - || self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) + || self.emit_obj == EmitObj::ObjectCode { bitcode_section: true } } } From d89f03f46062606b6ef35996c59029204934641f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 25 Mar 2020 13:28:09 +1100 Subject: [PATCH 2/8] Promote `-Zembed-bitcode` to `-Cembed-bitcode` and default to true. This means that bitcode embedding now occurs by default. Subsequent commits in this PR will remove the production of compressed bitcode in rlibs, and Cargo will soon start using this flag to avoid bitcode embedding when it's not necessary, which is most of the time. Also, produce an early error if `-Cembed-bitcode=no` is used with `-Clto`. --- src/librustc_codegen_ssa/back/write.rs | 3 ++- src/librustc_interface/tests.rs | 4 ++++ src/librustc_session/config.rs | 10 ++++++++++ src/librustc_session/options.rs | 4 ++-- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 0df9373a2618f..ab3767f377a84 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -131,7 +131,8 @@ impl ModuleConfig { || sess.opts.cg.linker_plugin_lto.enabled() { EmitObj::Bitcode - } else if sess.opts.debugging_opts.embed_bitcode { + } else if sess.opts.cg.embed_bitcode.unwrap_or(true) { + // `unwrap_or(true)` because `-C embed-bitcode` defaults to true. EmitObj::ObjectCode { bitcode_section: true } } else { EmitObj::ObjectCode { bitcode_section: false } diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index c75f3b279a258..b2e5f6c54edc1 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -505,6 +505,10 @@ fn test_codegen_options_tracking_hash() { opts = reference.clone(); opts.cg.linker_plugin_lto = LinkerPluginLto::LinkerPluginAuto; assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.embed_bitcode = Some(true); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); } #[test] diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index aaf30c583e263..56c577b12c907 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -1680,6 +1680,16 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { ); } + if let Some(false) = cg.embed_bitcode { + match cg.lto { + LtoCli::No | LtoCli::Unspecified => {} + LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => early_error( + error_format, + "options `-C embed-bitcode=no` and `-C lto` are incompatible", + ), + } + } + let prints = collect_print_requests(&mut cg, &mut debugging_opts, matches, error_format); let cg = cg; diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 8cd6ca86f4689..53b3065e22c60 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -727,6 +727,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "compile the program with profiling instrumentation"), profile_use: Option = (None, parse_opt_pathbuf, [TRACKED], "use the given `.profdata` file for profile-guided optimization"), + embed_bitcode: Option = (None, parse_opt_bool, [TRACKED], + "embed LLVM bitcode in object files (default: yes)"), } options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, @@ -926,8 +928,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "run `dsymutil` and delete intermediate object files"), ui_testing: Option = (None, parse_opt_bool, [UNTRACKED], "format compiler diagnostics in a way that's better suitable for UI testing"), - embed_bitcode: bool = (false, parse_bool, [TRACKED], - "embed LLVM bitcode in object files"), strip_debuginfo_if_disabled: Option = (None, parse_opt_bool, [TRACKED], "tell the linker to strip debuginfo when building without debuginfo enabled."), share_generics: Option = (None, parse_opt_bool, [TRACKED], From 7ae716fd6bba24abab37e98b3c83f272ece2b9ae Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 27 Mar 2020 10:51:53 +1100 Subject: [PATCH 3/8] Use embedded bitcode for LTO. Instead of `.bc.z` files. This requires adding some code that calls into LLVM to find the bitcode section within an object file. The name used for the LTO module is now the full filename, rather than a substring of the filename, which accounts for one test change. --- src/librustc_codegen_llvm/back/bytecode.rs | 2 + src/librustc_codegen_llvm/back/lto.rs | 46 +++++++++++++++------- src/librustc_codegen_llvm/llvm/ffi.rs | 5 +++ src/rustllvm/PassWrapper.cpp | 28 +++++++++++++ src/test/ui/lto-duplicate-symbols.stderr | 2 +- 5 files changed, 68 insertions(+), 15 deletions(-) diff --git a/src/librustc_codegen_llvm/back/bytecode.rs b/src/librustc_codegen_llvm/back/bytecode.rs index 0c8ce39132abb..18d1011c82cad 100644 --- a/src/librustc_codegen_llvm/back/bytecode.rs +++ b/src/librustc_codegen_llvm/back/bytecode.rs @@ -22,6 +22,8 @@ //! n+9.. compressed LLVM bitcode //! ? maybe a byte to make this whole thing even length +#![allow(dead_code)] // FIXME: this whole file will be removed in the next commit + use std::io::{Read, Write}; use std::ptr; use std::str; diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 816329e06c7a5..506ca3105bd29 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -1,4 +1,3 @@ -use crate::back::bytecode::DecodedBytecode; use crate::back::write::{ self, save_temp_bitcode, to_llvm_opt_settings, with_llvm_pmb, DiagnosticHandlers, }; @@ -10,7 +9,7 @@ use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModul use rustc_codegen_ssa::back::symbol_export; use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig}; use rustc_codegen_ssa::traits::*; -use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, RLIB_BYTECODE_EXTENSION}; +use rustc_codegen_ssa::{looks_like_rust_object_file, ModuleCodegen, ModuleKind}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{FatalError, Handler}; use rustc_hir::def_id::LOCAL_CRATE; @@ -111,22 +110,21 @@ fn prepare_lto( } let archive = ArchiveRO::open(&path).expect("wanted an rlib"); - let bytecodes = archive + let obj_files = archive .iter() .filter_map(|child| child.ok().and_then(|c| c.name().map(|name| (name, c)))) - .filter(|&(name, _)| name.ends_with(RLIB_BYTECODE_EXTENSION)); - for (name, data) in bytecodes { + .filter(|&(name, _)| looks_like_rust_object_file(name)); + for (name, data) in obj_files { let _timer = cgcx.prof.generic_activity_with_arg("LLVM_lto_load_upstream_bitcode", name); - info!("adding bytecode {}", name); - let bc_encoded = data.data(); - - let (bc, id) = match DecodedBytecode::new(bc_encoded) { - Ok(b) => Ok((b.bytecode(), b.identifier().to_string())), - Err(e) => Err(diag_handler.fatal(&e)), - }?; - let bc = SerializedModule::FromRlib(bc); - upstream_modules.push((bc, CString::new(id).unwrap())); + info!("adding bitcode from {}", name); + match get_bitcode_slice_from_object_data(data.data()) { + Ok(bc) => { + let bc = SerializedModule::FromRlib(bc.to_vec()); + upstream_modules.push((bc, CString::new(name).unwrap())); + } + Err(e) => return Err(diag_handler.fatal(&e)), + } } } } @@ -134,6 +132,26 @@ fn prepare_lto( Ok((symbol_white_list, upstream_modules)) } +fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], String> { + let mut len = 0; + let data = + unsafe { llvm::LLVMRustGetBitcodeSliceFromObjectData(obj.as_ptr(), obj.len(), &mut len) }; + if !data.is_null() { + assert!(len != 0); + let bc = unsafe { slice::from_raw_parts(data, len) }; + + // `bc` must be a sub-slice of `obj`. + assert!(obj.as_ptr() <= bc.as_ptr()); + assert!(bc[bc.len()..bc.len()].as_ptr() < obj[obj.len()..obj.len()].as_ptr()); + + Ok(bc) + } else { + assert!(len == 0); + let msg = llvm::last_error().unwrap_or_else(|| "unknown LLVM error".to_string()); + Err(format!("failed to get bitcode from object file for LTO ({})", msg)) + } +} + /// Performs fat LTO by merging all modules into a single one and returning it /// for further optimization. pub(crate) fn run_fat( diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index aeb34e5c9c954..ceeb528430fff 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -2138,6 +2138,11 @@ extern "C" { len: usize, Identifier: *const c_char, ) -> Option<&Module>; + pub fn LLVMRustGetBitcodeSliceFromObjectData( + Data: *const u8, + len: usize, + out_len: &mut usize, + ) -> *const u8; pub fn LLVMRustThinLTOGetDICompileUnit( M: &Module, CU1: &mut *mut c_void, diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 9e8614e3b6d34..5b955e6c949e2 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -13,6 +13,8 @@ #include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Verifier.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/IRObjectFile.h" #include "llvm/Passes/PassBuilder.h" #if LLVM_VERSION_GE(9, 0) #include "llvm/Passes/StandardInstrumentations.h" @@ -1496,6 +1498,32 @@ LLVMRustParseBitcodeForLTO(LLVMContextRef Context, return wrap(std::move(*SrcOrError).release()); } +// Find the bitcode section in the object file data and return it as a slice. +// Fail if the bitcode section is present but empty. +// +// On success, the return value is the pointer to the start of the slice and +// `out_len` is filled with the (non-zero) length. On failure, the return value +// is `nullptr` and `out_len` is set to zero. +extern "C" const char* +LLVMRustGetBitcodeSliceFromObjectData(const char *data, + size_t len, + size_t *out_len) { + *out_len = 0; + + StringRef Data(data, len); + MemoryBufferRef Buffer(Data, ""); // The id is unused. + + Expected BitcodeOrError = + object::IRObjectFile::findBitcodeInMemBuffer(Buffer); + if (!BitcodeOrError) { + LLVMRustSetLastError(toString(BitcodeOrError.takeError()).c_str()); + return nullptr; + } + + *out_len = BitcodeOrError->getBufferSize(); + return BitcodeOrError->getBufferStart(); +} + // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See // the comment in `back/lto.rs` for why this exists. extern "C" void diff --git a/src/test/ui/lto-duplicate-symbols.stderr b/src/test/ui/lto-duplicate-symbols.stderr index 02204830120a5..713b79bae32e6 100644 --- a/src/test/ui/lto-duplicate-symbols.stderr +++ b/src/test/ui/lto-duplicate-symbols.stderr @@ -1,6 +1,6 @@ warning: Linking globals named 'foo': symbol multiply defined! -error: failed to load bc of "lto_duplicate_symbols2.3a1fbbbh-cgu.0": +error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.3a1fbbbh-cgu.0.rcgu.o": error: aborting due to previous error; 1 warning emitted From 0d2cd698404b6f40a88e20da0d7a671e8bc58bc5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 25 Mar 2020 14:31:30 +1100 Subject: [PATCH 4/8] Remove `.bc.z` files. These were needed for LTO, but LTO now uses bitcode embedded in `.o` files. --- src/librustc_codegen_llvm/back/archive.rs | 6 +- src/librustc_codegen_llvm/back/bytecode.rs | 143 ------------------ src/librustc_codegen_llvm/back/write.rs | 17 +-- src/librustc_codegen_llvm/lib.rs | 1 - src/librustc_codegen_ssa/back/link.rs | 22 +-- src/librustc_codegen_ssa/back/write.rs | 32 ---- src/librustc_codegen_ssa/lib.rs | 18 +-- .../persist/work_product.rs | 1 - src/librustc_query_system/dep_graph/graph.rs | 1 - 9 files changed, 8 insertions(+), 233 deletions(-) delete mode 100644 src/librustc_codegen_llvm/back/bytecode.rs diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs index f1fe40d919eeb..a115a1e95163e 100644 --- a/src/librustc_codegen_llvm/back/archive.rs +++ b/src/librustc_codegen_llvm/back/archive.rs @@ -10,7 +10,7 @@ use std::str; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind}; use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder}; -use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME, RLIB_BYTECODE_EXTENSION}; +use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME}; use rustc_session::Session; use rustc_span::symbol::Symbol; @@ -129,8 +129,8 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { let obj_start = name.to_owned(); self.add_archive(rlib, move |fname: &str| { - // Ignore bytecode/metadata files, no matter the name. - if fname.ends_with(RLIB_BYTECODE_EXTENSION) || fname == METADATA_FILENAME { + // Ignore metadata files, no matter the name. + if fname == METADATA_FILENAME { return true; } diff --git a/src/librustc_codegen_llvm/back/bytecode.rs b/src/librustc_codegen_llvm/back/bytecode.rs deleted file mode 100644 index 18d1011c82cad..0000000000000 --- a/src/librustc_codegen_llvm/back/bytecode.rs +++ /dev/null @@ -1,143 +0,0 @@ -//! Management of the encoding of LLVM bytecode into rlibs -//! -//! This module contains the management of encoding LLVM bytecode into rlibs, -//! primarily for the usage in LTO situations. Currently the compiler will -//! unconditionally encode LLVM-IR into rlibs regardless of what's happening -//! elsewhere, so we currently compress the bytecode via deflate to avoid taking -//! up too much space on disk. -//! -//! After compressing the bytecode we then have the rest of the format to -//! basically deal with various bugs in various archive implementations. The -//! format currently is: -//! -//! RLIB LLVM-BYTECODE OBJECT LAYOUT -//! Version 2 -//! Bytes Data -//! 0..10 "RUST_OBJECT" encoded in ASCII -//! 11..14 format version as little-endian u32 -//! 15..19 the length of the module identifier string -//! 20..n the module identifier string -//! n..n+8 size in bytes of deflate compressed LLVM bitcode as -//! little-endian u64 -//! n+9.. compressed LLVM bitcode -//! ? maybe a byte to make this whole thing even length - -#![allow(dead_code)] // FIXME: this whole file will be removed in the next commit - -use std::io::{Read, Write}; -use std::ptr; -use std::str; - -use flate2::read::DeflateDecoder; -use flate2::write::DeflateEncoder; -use flate2::Compression; - -// This is the "magic number" expected at the beginning of a LLVM bytecode -// object in an rlib. -pub const RLIB_BYTECODE_OBJECT_MAGIC: &[u8] = b"RUST_OBJECT"; - -// The version number this compiler will write to bytecode objects in rlibs -pub const RLIB_BYTECODE_OBJECT_VERSION: u8 = 2; - -pub fn encode(identifier: &str, bytecode: &[u8]) -> Vec { - let mut encoded = Vec::new(); - - // Start off with the magic string - encoded.extend_from_slice(RLIB_BYTECODE_OBJECT_MAGIC); - - // Next up is the version - encoded.extend_from_slice(&[RLIB_BYTECODE_OBJECT_VERSION, 0, 0, 0]); - - // Next is the LLVM module identifier length + contents - let identifier_len = identifier.len(); - encoded.extend_from_slice(&[ - (identifier_len >> 0) as u8, - (identifier_len >> 8) as u8, - (identifier_len >> 16) as u8, - (identifier_len >> 24) as u8, - ]); - encoded.extend_from_slice(identifier.as_bytes()); - - // Next is the LLVM module deflate compressed, prefixed with its length. We - // don't know its length yet, so fill in 0s - let deflated_size_pos = encoded.len(); - encoded.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); - - let before = encoded.len(); - DeflateEncoder::new(&mut encoded, Compression::fast()).write_all(bytecode).unwrap(); - let after = encoded.len(); - - // Fill in the length we reserved space for before - let bytecode_len = (after - before) as u64; - encoded[deflated_size_pos + 0] = (bytecode_len >> 0) as u8; - encoded[deflated_size_pos + 1] = (bytecode_len >> 8) as u8; - encoded[deflated_size_pos + 2] = (bytecode_len >> 16) as u8; - encoded[deflated_size_pos + 3] = (bytecode_len >> 24) as u8; - encoded[deflated_size_pos + 4] = (bytecode_len >> 32) as u8; - encoded[deflated_size_pos + 5] = (bytecode_len >> 40) as u8; - encoded[deflated_size_pos + 6] = (bytecode_len >> 48) as u8; - encoded[deflated_size_pos + 7] = (bytecode_len >> 56) as u8; - - // If the number of bytes written to the object so far is odd, add a - // padding byte to make it even. This works around a crash bug in LLDB - // (see issue #15950) - if encoded.len() % 2 == 1 { - encoded.push(0); - } - - encoded -} - -pub struct DecodedBytecode<'a> { - identifier: &'a str, - encoded_bytecode: &'a [u8], -} - -impl<'a> DecodedBytecode<'a> { - pub fn new(data: &'a [u8]) -> Result, &'static str> { - if !data.starts_with(RLIB_BYTECODE_OBJECT_MAGIC) { - return Err("magic bytecode prefix not found"); - } - let data = &data[RLIB_BYTECODE_OBJECT_MAGIC.len()..]; - if !data.starts_with(&[RLIB_BYTECODE_OBJECT_VERSION, 0, 0, 0]) { - return Err("wrong version prefix found in bytecode"); - } - let data = &data[4..]; - if data.len() < 4 { - return Err("bytecode corrupted"); - } - let identifier_len = - unsafe { u32::from_le(ptr::read_unaligned(data.as_ptr() as *const u32)) as usize }; - let data = &data[4..]; - if data.len() < identifier_len { - return Err("bytecode corrupted"); - } - let identifier = match str::from_utf8(&data[..identifier_len]) { - Ok(s) => s, - Err(_) => return Err("bytecode corrupted"), - }; - let data = &data[identifier_len..]; - if data.len() < 8 { - return Err("bytecode corrupted"); - } - let bytecode_len = - unsafe { u64::from_le(ptr::read_unaligned(data.as_ptr() as *const u64)) as usize }; - let data = &data[8..]; - if data.len() < bytecode_len { - return Err("bytecode corrupted"); - } - let encoded_bytecode = &data[..bytecode_len]; - - Ok(DecodedBytecode { identifier, encoded_bytecode }) - } - - pub fn bytecode(&self) -> Vec { - let mut data = Vec::new(); - DeflateDecoder::new(self.encoded_bytecode).read_to_end(&mut data).unwrap(); - data - } - - pub fn identifier(&self) -> &'a str { - self.identifier - } -} diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 378263f2adabb..bb367b5efb6d4 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -1,5 +1,4 @@ use crate::attributes; -use crate::back::bytecode; use crate::back::lto::ThinBuffer; use crate::back::profiling::{ selfprofile_after_pass_callback, selfprofile_before_pass_callback, LlvmSelfProfiler, @@ -16,7 +15,7 @@ use crate::ModuleLlvm; use log::debug; use rustc_codegen_ssa::back::write::{CodegenContext, EmitObj, ModuleConfig}; use rustc_codegen_ssa::traits::*; -use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, RLIB_BYTECODE_EXTENSION}; +use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; use rustc_data_structures::small_c_str::SmallCStr; use rustc_errors::{FatalError, Handler}; use rustc_fs_util::{link_or_copy, path_to_c_string}; @@ -669,19 +668,6 @@ pub(crate) unsafe fn codegen( ); embed_bitcode(cgcx, llcx, llmod, data); } - - if config.emit_bc_compressed { - let _timer = cgcx.prof.generic_activity_with_arg( - "LLVM_module_codegen_emit_compressed_bitcode", - &module.name[..], - ); - let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION); - let data = bytecode::encode(&module.name, data); - if let Err(e) = fs::write(&dst, data) { - let msg = format!("failed to write bytecode to {}: {}", dst.display(), e); - diag_handler.err(&msg); - } - } } if config.emit_ir { @@ -790,7 +776,6 @@ pub(crate) unsafe fn codegen( Ok(module.into_compiled_module( config.emit_obj != EmitObj::None, config.emit_bc, - config.emit_bc_compressed, &cgcx.output_filenames, )) } diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 939f9e9c2a0c7..5d4c7109d6580 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -39,7 +39,6 @@ use std::sync::Arc; mod back { pub mod archive; - pub mod bytecode; pub mod lto; mod profiling; pub mod write; diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 4c66d901e7a99..77cec347448a5 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -18,10 +18,7 @@ use super::archive::ArchiveBuilder; use super::command::Command; use super::linker::Linker; use super::rpath::{self, RPathConfig}; -use crate::{ - looks_like_rust_object_file, CodegenResults, CrateInfo, METADATA_FILENAME, - RLIB_BYTECODE_EXTENSION, -}; +use crate::{looks_like_rust_object_file, CodegenResults, CrateInfo, METADATA_FILENAME}; use cc::windows_registry; use tempfile::{Builder as TempFileBuilder, TempDir}; @@ -130,10 +127,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( remove(sess, obj); } } - for obj in codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) - { - remove(sess, obj); - } if let Some(ref metadata_module) = codegen_results.metadata_module { if let Some(ref obj) = metadata_module.object { remove(sess, obj); @@ -143,9 +136,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( if let Some(ref obj) = allocator_module.object { remove(sess, obj); } - if let Some(ref bc) = allocator_module.bytecode_compressed { - remove(sess, bc); - } } } }); @@ -378,14 +368,6 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( // contain the metadata in a separate file. ab.add_file(&emit_metadata(sess, &codegen_results.metadata, tmpdir)); - // For LTO purposes, the bytecode of this library is also inserted - // into the archive. - for bytecode in - codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) - { - ab.add_file(bytecode); - } - // After adding all files to the archive, we need to update the // symbol table of the archive. This currently dies on macOS (see // #11162), and isn't necessary there anyway @@ -1842,7 +1824,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( let mut any_objects = false; for f in archive.src_files() { - if f.ends_with(RLIB_BYTECODE_EXTENSION) || f == METADATA_FILENAME { + if f == METADATA_FILENAME { archive.remove_file(&f); continue; } diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index ab3767f377a84..41f852f7563c5 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -5,7 +5,6 @@ use super::symbol_export::symbol_name_for_instance_in_crate; use crate::{ CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind, - RLIB_BYTECODE_EXTENSION, }; use crate::traits::*; @@ -86,7 +85,6 @@ pub struct ModuleConfig { pub emit_pre_lto_bc: bool, pub emit_no_opt_bc: bool, pub emit_bc: bool, - pub emit_bc_compressed: bool, pub emit_ir: bool, pub emit_asm: bool, pub emit_obj: EmitObj, @@ -178,16 +176,6 @@ impl ModuleConfig { save_temps || sess.opts.output_types.contains_key(&OutputType::Bitcode), save_temps ), - emit_bc_compressed: match kind { - ModuleKind::Regular | ModuleKind::Allocator => { - // Emit compressed bitcode files for the crate if we're - // emitting an rlib. Whenever an rlib is created, the - // bitcode is inserted into the archive in order to allow - // LTO against it. - need_crate_bitcode_for_rlib(sess) - } - ModuleKind::Metadata => false, - }, emit_ir: if_regular!( sess.opts.output_types.contains_key(&OutputType::LlvmAssembly), false @@ -243,7 +231,6 @@ impl ModuleConfig { pub fn bitcode_needed(&self) -> bool { self.emit_bc - || self.emit_bc_compressed || self.emit_obj == EmitObj::Bitcode || self.emit_obj == EmitObj::ObjectCode { bitcode_section: true } } @@ -359,11 +346,6 @@ pub struct CompiledModules { pub allocator_module: Option, } -fn need_crate_bitcode_for_rlib(sess: &Session) -> bool { - sess.crate_types.borrow().contains(&config::CrateType::Rlib) - && sess.opts.output_types.contains_key(&OutputType::Exe) -} - fn need_pre_lto_bitcode_for_incr_comp(sess: &Session) -> bool { if sess.opts.incremental.is_none() { return false; @@ -463,9 +445,6 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( if let Some(ref path) = module.bytecode { files.push((WorkProductFileKind::Bytecode, path.clone())); } - if let Some(ref path) = module.bytecode_compressed { - files.push((WorkProductFileKind::BytecodeCompressed, path.clone())); - } if let Some((id, product)) = copy_cgu_workproducts_to_incr_comp_cache_dir(sess, &module.name, &files) @@ -802,7 +781,6 @@ fn execute_copy_from_cache_work_item( let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); let mut object = None; let mut bytecode = None; - let mut bytecode_compressed = None; for (kind, saved_file) in &module.source.saved_files { let obj_out = match kind { WorkProductFileKind::Object => { @@ -815,14 +793,6 @@ fn execute_copy_from_cache_work_item( bytecode = Some(path.clone()); path } - WorkProductFileKind::BytecodeCompressed => { - let path = cgcx - .output_filenames - .temp_path(OutputType::Bitcode, Some(&module.name)) - .with_extension(RLIB_BYTECODE_EXTENSION); - bytecode_compressed = Some(path.clone()); - path - } }; let source_file = in_incr_comp_dir(&incr_comp_session_dir, &saved_file); debug!( @@ -844,14 +814,12 @@ fn execute_copy_from_cache_work_item( assert_eq!(object.is_some(), module_config.emit_obj != EmitObj::None); assert_eq!(bytecode.is_some(), module_config.emit_bc); - assert_eq!(bytecode_compressed.is_some(), module_config.emit_bc_compressed); Ok(WorkItemResult::Compiled(CompiledModule { name: module.name, kind: ModuleKind::Regular, object, bytecode, - bytecode_compressed, })) } diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index bf8441562c55b..fbe0d29a9a936 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -54,31 +54,18 @@ pub struct ModuleCodegen { // FIXME(eddyb) maybe include the crate name in this? pub const METADATA_FILENAME: &str = "lib.rmeta"; -pub const RLIB_BYTECODE_EXTENSION: &str = "bc.z"; impl ModuleCodegen { pub fn into_compiled_module( self, emit_obj: bool, emit_bc: bool, - emit_bc_compressed: bool, outputs: &OutputFilenames, ) -> CompiledModule { let object = emit_obj.then(|| outputs.temp_path(OutputType::Object, Some(&self.name))); let bytecode = emit_bc.then(|| outputs.temp_path(OutputType::Bitcode, Some(&self.name))); - let bytecode_compressed = emit_bc_compressed.then(|| { - outputs - .temp_path(OutputType::Bitcode, Some(&self.name)) - .with_extension(RLIB_BYTECODE_EXTENSION) - }); - - CompiledModule { - name: self.name.clone(), - kind: self.kind, - object, - bytecode, - bytecode_compressed, - } + + CompiledModule { name: self.name.clone(), kind: self.kind, object, bytecode } } } @@ -88,7 +75,6 @@ pub struct CompiledModule { pub kind: ModuleKind, pub object: Option, pub bytecode: Option, - pub bytecode_compressed: Option, } pub struct CachedModuleCodegen { diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index 4dd81b1df5759..3601b99705916 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -21,7 +21,6 @@ pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( let extension = match kind { WorkProductFileKind::Object => "o", WorkProductFileKind::Bytecode => "bc", - WorkProductFileKind::BytecodeCompressed => "bc.z", }; let file_name = format!("{}.{}", cgu_name, extension); let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name); diff --git a/src/librustc_query_system/dep_graph/graph.rs b/src/librustc_query_system/dep_graph/graph.rs index fa2b51058a378..ba3ce16ae36fe 100644 --- a/src/librustc_query_system/dep_graph/graph.rs +++ b/src/librustc_query_system/dep_graph/graph.rs @@ -868,7 +868,6 @@ pub struct WorkProduct { pub enum WorkProductFileKind { Object, Bytecode, - BytecodeCompressed, } #[derive(Clone)] From f2680fc229359053b581c1a422344875c8d0c457 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 31 Mar 2020 10:41:59 +1100 Subject: [PATCH 5/8] Don't copy bytecode files into the incr. comp. cache. It's no longer necessary now that bitcode is embedded into object files. This change meant that `WorkProductFileKind::Bytecode` is no longer necessary, which means that type is no longer necessary, which allowed several places in the code to become simpler. --- src/librustc_codegen_ssa/back/write.rs | 27 +++++-------------- src/librustc_incremental/persist/load.rs | 2 +- src/librustc_incremental/persist/save.rs | 8 +++--- .../persist/work_product.rs | 16 +++++------ src/librustc_middle/dep_graph/mod.rs | 2 +- src/librustc_query_system/dep_graph/graph.rs | 8 +----- src/librustc_query_system/dep_graph/mod.rs | 1 - 7 files changed, 19 insertions(+), 45 deletions(-) diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 41f852f7563c5..7d161ef3cf122 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -23,7 +23,7 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_incremental::{ copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess, }; -use rustc_middle::dep_graph::{WorkProduct, WorkProductFileKind, WorkProductId}; +use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::cstore::EncodedMetadata; use rustc_middle::middle::exported_symbols::SymbolExportLevel; use rustc_middle::ty::TyCtxt; @@ -440,10 +440,7 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( let mut files = vec![]; if let Some(ref path) = module.object { - files.push((WorkProductFileKind::Object, path.clone())); - } - if let Some(ref path) = module.bytecode { - files.push((WorkProductFileKind::Bytecode, path.clone())); + files.push(path.clone()); } if let Some((id, product)) = @@ -780,20 +777,9 @@ fn execute_copy_from_cache_work_item( ) -> Result, FatalError> { let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); let mut object = None; - let mut bytecode = None; - for (kind, saved_file) in &module.source.saved_files { - let obj_out = match kind { - WorkProductFileKind::Object => { - let path = cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name)); - object = Some(path.clone()); - path - } - WorkProductFileKind::Bytecode => { - let path = cgcx.output_filenames.temp_path(OutputType::Bitcode, Some(&module.name)); - bytecode = Some(path.clone()); - path - } - }; + for saved_file in &module.source.saved_files { + let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name)); + object = Some(obj_out.clone()); let source_file = in_incr_comp_dir(&incr_comp_session_dir, &saved_file); debug!( "copying pre-existing module `{}` from {:?} to {}", @@ -813,13 +799,12 @@ fn execute_copy_from_cache_work_item( } assert_eq!(object.is_some(), module_config.emit_obj != EmitObj::None); - assert_eq!(bytecode.is_some(), module_config.emit_bc); Ok(WorkItemResult::Compiled(CompiledModule { name: module.name, kind: ModuleKind::Regular, object, - bytecode, + bytecode: None, })) } diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index b75a428c62a09..99c799950c063 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -134,7 +134,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { for swp in work_products { let mut all_files_exist = true; - for &(_, ref file_name) in swp.work_product.saved_files.iter() { + for file_name in swp.work_product.saved_files.iter() { let path = in_incr_comp_dir_sess(sess, file_name); if !path.exists() { all_files_exist = false; diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 6d4ba45c2e6ed..4db6297712c59 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -74,9 +74,9 @@ pub fn save_work_product_index( if !new_work_products.contains_key(id) { work_product::delete_workproduct_files(sess, wp); debug_assert!( - wp.saved_files.iter().all(|&(_, ref file_name)| { - !in_incr_comp_dir_sess(sess, file_name).exists() - }) + wp.saved_files + .iter() + .all(|file_name| { !in_incr_comp_dir_sess(sess, file_name).exists() }) ); } } @@ -85,7 +85,7 @@ pub fn save_work_product_index( debug_assert!({ new_work_products .iter() - .flat_map(|(_, wp)| wp.saved_files.iter().map(|&(_, ref name)| name)) + .flat_map(|(_, wp)| wp.saved_files.iter()) .map(|name| in_incr_comp_dir_sess(sess, name)) .all(|path| path.exists()) }); diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index 3601b99705916..a15ee6d81dbbc 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -2,7 +2,7 @@ use crate::persist::fs::*; use rustc_fs_util::link_or_copy; -use rustc_middle::dep_graph::{WorkProduct, WorkProductFileKind, WorkProductId}; +use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_session::Session; use std::fs as std_fs; use std::path::PathBuf; @@ -10,22 +10,18 @@ use std::path::PathBuf; pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( sess: &Session, cgu_name: &str, - files: &[(WorkProductFileKind, PathBuf)], + files: &[PathBuf], ) -> Option<(WorkProductId, WorkProduct)> { debug!("copy_cgu_workproducts_to_incr_comp_cache_dir({:?},{:?})", cgu_name, files); sess.opts.incremental.as_ref()?; let saved_files = files .iter() - .map(|&(kind, ref path)| { - let extension = match kind { - WorkProductFileKind::Object => "o", - WorkProductFileKind::Bytecode => "bc", - }; - let file_name = format!("{}.{}", cgu_name, extension); + .map(|path| { + let file_name = format!("{}.o", cgu_name); let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name); match link_or_copy(path, &path_in_incr_dir) { - Ok(_) => Some((kind, file_name)), + Ok(_) => Some(file_name), Err(err) => { sess.warn(&format!( "error copying object file `{}` \ @@ -47,7 +43,7 @@ pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( } pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) { - for &(_, ref file_name) in &work_product.saved_files { + for file_name in &work_product.saved_files { let path = in_incr_comp_dir_sess(sess, file_name); match std_fs::remove_file(&path) { Ok(()) => {} diff --git a/src/librustc_middle/dep_graph/mod.rs b/src/librustc_middle/dep_graph/mod.rs index f56df19bfb061..34add7f7a99eb 100644 --- a/src/librustc_middle/dep_graph/mod.rs +++ b/src/librustc_middle/dep_graph/mod.rs @@ -12,7 +12,7 @@ mod dep_node; pub(crate) use rustc_query_system::dep_graph::DepNodeParams; pub use rustc_query_system::dep_graph::{ debug, hash_result, DepContext, DepNodeColor, DepNodeIndex, SerializedDepNodeIndex, - WorkProduct, WorkProductFileKind, WorkProductId, + WorkProduct, WorkProductId, }; pub use dep_node::{label_strs, DepConstructor, DepKind, DepNode, DepNodeExt}; diff --git a/src/librustc_query_system/dep_graph/graph.rs b/src/librustc_query_system/dep_graph/graph.rs index ba3ce16ae36fe..5f14a09b24daa 100644 --- a/src/librustc_query_system/dep_graph/graph.rs +++ b/src/librustc_query_system/dep_graph/graph.rs @@ -861,13 +861,7 @@ impl DepGraph { pub struct WorkProduct { pub cgu_name: String, /// Saved files associated with this CGU. - pub saved_files: Vec<(WorkProductFileKind, String)>, -} - -#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable, PartialEq)] -pub enum WorkProductFileKind { - Object, - Bytecode, + pub saved_files: Vec, } #[derive(Clone)] diff --git a/src/librustc_query_system/dep_graph/mod.rs b/src/librustc_query_system/dep_graph/mod.rs index fbc91575ede41..4acb70c7e803b 100644 --- a/src/librustc_query_system/dep_graph/mod.rs +++ b/src/librustc_query_system/dep_graph/mod.rs @@ -6,7 +6,6 @@ mod query; mod serialized; pub use dep_node::{DepNode, DepNodeParams, WorkProductId}; -pub use graph::WorkProductFileKind; pub use graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, WorkProduct}; pub use prev::PreviousDepGraph; pub use query::DepGraphQuery; From 8b1fc0e46865bbea938e0bc54c16ed515b856068 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 2 Apr 2020 06:27:05 +1100 Subject: [PATCH 6/8] Document `-C embed-bitcode` in the rustc book. --- src/doc/rustc/src/codegen-options/index.md | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 8dc6257ce2e58..49750ba26604a 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -381,6 +381,31 @@ the linker. The default is `yes` if not specified. +## embed-bitcode + +This flag controls whether or not the compiler embeds LLVM bitcode into +generated object files. It takes one of the following values: + +* `y`, `yes`, `on`, or no value: enable bitcode embedding (the default). +* `n`, `no`, or `off`: disable bitcode embedding. + +LLVM bitcode embedding is only needed when link-time optimization (LTO) is +being performed, but it is enabled by default for backwards compatibility +reasons. + +The use of `-C embed-bitcode=no` can significantly improve compile times and +reduce generated file sizes. For these reasons, Cargo uses `-C +embed-bitcode=no` whenever appropriate to reduce compilation costs. Likewise, +if you are building directly with `rustc` we recommend using `-C +embed-bitcode=no` whenever you are not using LTO. + +If combined with `-C lto`, `-C embed-bitcode=no` will cause `rustc` to abort at +start-up, because the combination is invalid. + +If combined with `-C linker-plugin-lto`, `-C embed-bitcode` (with any value) +will be ignored, because in that case generated object files contain only LLVM +bitcode, and no object code. + [option-emit]: ../command-line-arguments.md#option-emit [option-o-optimize]: ../command-line-arguments.md#option-o-optimize [profile-guided optimization]: ../profile-guided-optimization.md From 2c18cc160f2e157a819bb3a5d9194729eee9aacb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 3 Apr 2020 09:44:15 +1100 Subject: [PATCH 7/8] Build libstd with `-Cembed-bitcode=yes`. So that the artifacts will work with both LTO and non-LTO builds. --- src/bootstrap/check.rs | 2 +- src/bootstrap/compile.rs | 14 ++++++++++++-- src/bootstrap/doc.rs | 2 +- src/bootstrap/test.rs | 2 +- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index b76515763fbdb..586a362b5e3fe 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -45,7 +45,7 @@ impl Step for Std { let compiler = builder.compiler(0, builder.config.build); let mut cargo = builder.cargo(compiler, Mode::Std, target, cargo_subcommand(builder.kind)); - std_cargo(builder, target, &mut cargo); + std_cargo(builder, target, compiler.stage, &mut cargo); builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target)); run_cargo( diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index f44096af6dd53..c7ae73f9f8b91 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -86,7 +86,7 @@ impl Step for Std { target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter()); let mut cargo = builder.cargo(compiler, Mode::Std, target, "build"); - std_cargo(builder, target, &mut cargo); + std_cargo(builder, target, compiler.stage, &mut cargo); builder.info(&format!( "Building stage{} std artifacts ({} -> {})", @@ -164,7 +164,7 @@ fn copy_third_party_objects( /// Configure cargo to compile the standard library, adding appropriate env vars /// and such. -pub fn std_cargo(builder: &Builder<'_>, target: Interned, cargo: &mut Cargo) { +pub fn std_cargo(builder: &Builder<'_>, target: Interned, stage: u32, cargo: &mut Cargo) { if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } @@ -231,6 +231,16 @@ pub fn std_cargo(builder: &Builder<'_>, target: Interned, cargo: &mut Ca } } } + + // libstd must be built with embedded bitcode so that the produced + // artifacts can be used for both LTO builds (which use bitcode) and + // non-LTO builds (which use object code). + // + // But we don't bother for the stage 0 compiler because it's never used + // with LTO. + if stage >= 1 { + cargo.rustflag("-Cembed-bitcode=yes"); + } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 04da3cc1015b8..fc217a707db94 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -394,7 +394,7 @@ impl Step for Std { let run_cargo_rustdoc_for = |package: &str| { let mut cargo = builder.cargo(compiler, Mode::Std, target, "rustdoc"); - compile::std_cargo(builder, target, &mut cargo); + compile::std_cargo(builder, target, compiler.stage, &mut cargo); // Keep a whitelist so we do not build internal stdlib crates, these will be // build by the rustc step later if enabled. diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 85c5d28bb8924..125563b7b6086 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1725,7 +1725,7 @@ impl Step for Crate { let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand()); match mode { Mode::Std => { - compile::std_cargo(builder, target, &mut cargo); + compile::std_cargo(builder, target, compiler.stage, &mut cargo); } Mode::Rustc => { builder.ensure(compile::Rustc { compiler, target }); From f86c8aa3252ed34678ddbba5451264ea9d372d78 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 17 Apr 2020 09:03:57 +1000 Subject: [PATCH 8/8] Update llvm-project. In order to get rust-lang/llvm-project#48, which is needed for wasm to work in this PR (#70458). --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 9f9da27fbdb0b..3ba91917e52bd 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 9f9da27fbdb0ba7d887f8d2521e082f12b009417 +Subproject commit 3ba91917e52bd66ac37161ad4a1bc87d32aa2e18