Introduce EmitObj
.
Currently, there are three fields in `ModuleConfig` that dictate how object files are emitted: `emit_obj`, `obj_is_bitcode`, and `embed_bitcode`. Some of the combinations of these fields are nonsensical, in particular having both `obj_is_bitcode` and `embed_bitcode` true at the same time. Also, currently: - we needlessly emit and then delete a bytecode file if `obj_is_bitcode` is true but `emit_obj` is false; - we needlessly embed bitcode in the LLVM module if `embed_bitcode` is true and `emit_obj` is false. This commit combines the three fields into one, with a new type `EmitObj` (and the auxiliary `BitcodeSection`) which can encode five different possibilities. In the old code, `set_flags` would set `obj_is_bitcode` and `embed_bitcode` on all three of the configs (`modules`, `allocator`, `metadata`) if the relevant other conditions were met, even if no object code needed to be emitted for one or more of them. Whereas `start_async_codegen` would set `emit_obj`, but only for those configs that need it. In the new code, `start_async_codegen` does all the work of setting `emit_obj`, and it only does that for the configs that need it. `set_flags` no longer sets anything related to object file emission.
This commit is contained in:
parent
e1d1db790f
commit
87ef16c9dc
@ -16,7 +16,9 @@ use crate::ModuleLlvm;
|
|||||||
use log::debug;
|
use log::debug;
|
||||||
use rustc::bug;
|
use rustc::bug;
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc_codegen_ssa::back::write::{run_assembler, CodegenContext, EmbedBitcode, ModuleConfig};
|
use rustc_codegen_ssa::back::write::{
|
||||||
|
run_assembler, BitcodeSection, CodegenContext, EmitObj, ModuleConfig,
|
||||||
|
};
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, RLIB_BYTECODE_EXTENSION};
|
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, RLIB_BYTECODE_EXTENSION};
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
@ -651,7 +653,7 @@ pub(crate) unsafe fn codegen(
|
|||||||
let thin = ThinBuffer::new(llmod);
|
let thin = ThinBuffer::new(llmod);
|
||||||
let data = thin.data();
|
let data = thin.data();
|
||||||
|
|
||||||
if config.emit_bc || config.obj_is_bitcode {
|
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
|
||||||
let _timer = cgcx.prof.generic_activity_with_arg(
|
let _timer = cgcx.prof.generic_activity_with_arg(
|
||||||
"LLVM_module_codegen_emit_bitcode",
|
"LLVM_module_codegen_emit_bitcode",
|
||||||
&module.name[..],
|
&module.name[..],
|
||||||
@ -662,7 +664,7 @@ pub(crate) unsafe fn codegen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.embed_bitcode == EmbedBitcode::Full {
|
if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
|
||||||
let _timer = cgcx.prof.generic_activity_with_arg(
|
let _timer = cgcx.prof.generic_activity_with_arg(
|
||||||
"LLVM_module_codegen_embed_bitcode",
|
"LLVM_module_codegen_embed_bitcode",
|
||||||
&module.name[..],
|
&module.name[..],
|
||||||
@ -682,7 +684,7 @@ pub(crate) unsafe fn codegen(
|
|||||||
diag_handler.err(&msg);
|
diag_handler.err(&msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if config.embed_bitcode == EmbedBitcode::Marker {
|
} else if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Marker) {
|
||||||
embed_bitcode(cgcx, llcx, llmod, None);
|
embed_bitcode(cgcx, llcx, llmod, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,9 +734,9 @@ pub(crate) unsafe fn codegen(
|
|||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let config_emit_normal_obj = config.emit_obj && !config.obj_is_bitcode;
|
let config_emit_object_code = matches!(config.emit_obj, EmitObj::ObjectCode(_));
|
||||||
|
|
||||||
if config.emit_asm || (config_emit_normal_obj && config.no_integrated_as) {
|
if config.emit_asm || (config_emit_object_code && config.no_integrated_as) {
|
||||||
let _timer = cgcx
|
let _timer = cgcx
|
||||||
.prof
|
.prof
|
||||||
.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]);
|
.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]);
|
||||||
@ -743,13 +745,13 @@ pub(crate) unsafe fn codegen(
|
|||||||
// We can't use the same module for asm and binary output, because that triggers
|
// We can't use the same module for asm and binary output, because that triggers
|
||||||
// various errors like invalid IR or broken binaries, so we might have to clone the
|
// various errors like invalid IR or broken binaries, so we might have to clone the
|
||||||
// module to produce the asm output
|
// module to produce the asm output
|
||||||
let llmod = if config.emit_obj { llvm::LLVMCloneModule(llmod) } else { llmod };
|
let llmod = if config_emit_object_code { llvm::LLVMCloneModule(llmod) } else { llmod };
|
||||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||||
write_output_file(diag_handler, tm, cpm, llmod, &path, llvm::FileType::AssemblyFile)
|
write_output_file(diag_handler, tm, cpm, llmod, &path, llvm::FileType::AssemblyFile)
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if config_emit_normal_obj {
|
if config_emit_object_code {
|
||||||
if !config.no_integrated_as {
|
if !config.no_integrated_as {
|
||||||
let _timer = cgcx
|
let _timer = cgcx
|
||||||
.prof
|
.prof
|
||||||
@ -775,14 +777,10 @@ pub(crate) unsafe fn codegen(
|
|||||||
drop(fs::remove_file(&assembly));
|
drop(fs::remove_file(&assembly));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if config.emit_obj == EmitObj::Bitcode {
|
||||||
|
debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
|
||||||
if config.obj_is_bitcode {
|
if let Err(e) = link_or_copy(&bc_out, &obj_out) {
|
||||||
if config.emit_obj {
|
diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
|
||||||
debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
|
|
||||||
if let Err(e) = link_or_copy(&bc_out, &obj_out) {
|
|
||||||
diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !config.emit_bc {
|
if !config.emit_bc {
|
||||||
@ -796,7 +794,7 @@ pub(crate) unsafe fn codegen(
|
|||||||
drop(handlers);
|
drop(handlers);
|
||||||
}
|
}
|
||||||
Ok(module.into_compiled_module(
|
Ok(module.into_compiled_module(
|
||||||
config.emit_obj,
|
config.emit_obj != EmitObj::None,
|
||||||
config.emit_bc,
|
config.emit_bc,
|
||||||
config.emit_bc_compressed,
|
config.emit_bc_compressed,
|
||||||
&cgcx.output_filenames,
|
&cgcx.output_filenames,
|
||||||
|
@ -51,11 +51,31 @@ use std::thread;
|
|||||||
|
|
||||||
const PRE_LTO_BC_EXT: &str = "pre-lto.bc";
|
const PRE_LTO_BC_EXT: &str = "pre-lto.bc";
|
||||||
|
|
||||||
/// The kind of bitcode to embed in object files.
|
/// What kind of object file to emit.
|
||||||
#[derive(PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub enum EmbedBitcode {
|
pub enum EmitObj {
|
||||||
|
// No object file.
|
||||||
None,
|
None,
|
||||||
|
|
||||||
|
// Just uncompressed llvm bitcode. Provides easy compatibility with
|
||||||
|
// emscripten's ecc compiler, when used as the linker.
|
||||||
|
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,
|
Marker,
|
||||||
|
|
||||||
|
// A full, uncompressed bitcode section.
|
||||||
Full,
|
Full,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +104,7 @@ pub struct ModuleConfig {
|
|||||||
pub emit_bc_compressed: bool,
|
pub emit_bc_compressed: bool,
|
||||||
pub emit_ir: bool,
|
pub emit_ir: bool,
|
||||||
pub emit_asm: bool,
|
pub emit_asm: bool,
|
||||||
pub emit_obj: bool,
|
pub emit_obj: EmitObj,
|
||||||
// Miscellaneous flags. These are mostly copied from command-line
|
// Miscellaneous flags. These are mostly copied from command-line
|
||||||
// options.
|
// options.
|
||||||
pub verify_llvm_ir: bool,
|
pub verify_llvm_ir: bool,
|
||||||
@ -96,12 +116,7 @@ pub struct ModuleConfig {
|
|||||||
pub merge_functions: bool,
|
pub merge_functions: bool,
|
||||||
pub inline_threshold: Option<usize>,
|
pub inline_threshold: Option<usize>,
|
||||||
pub new_llvm_pass_manager: Option<bool>,
|
pub new_llvm_pass_manager: Option<bool>,
|
||||||
// Instead of creating an object file by doing LLVM codegen, just
|
|
||||||
// make the object file bitcode. Provides easy compatibility with
|
|
||||||
// emscripten's ecc compiler, when used as the linker.
|
|
||||||
pub obj_is_bitcode: bool,
|
|
||||||
pub no_integrated_as: bool,
|
pub no_integrated_as: bool,
|
||||||
pub embed_bitcode: EmbedBitcode,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleConfig {
|
impl ModuleConfig {
|
||||||
@ -124,9 +139,7 @@ impl ModuleConfig {
|
|||||||
emit_bc_compressed: false,
|
emit_bc_compressed: false,
|
||||||
emit_ir: false,
|
emit_ir: false,
|
||||||
emit_asm: false,
|
emit_asm: false,
|
||||||
emit_obj: false,
|
emit_obj: EmitObj::None,
|
||||||
obj_is_bitcode: false,
|
|
||||||
embed_bitcode: EmbedBitcode::None,
|
|
||||||
no_integrated_as: false,
|
no_integrated_as: false,
|
||||||
|
|
||||||
verify_llvm_ir: false,
|
verify_llvm_ir: false,
|
||||||
@ -147,16 +160,6 @@ impl ModuleConfig {
|
|||||||
self.no_builtins = no_builtins || sess.target.target.options.no_builtins;
|
self.no_builtins = no_builtins || sess.target.target.options.no_builtins;
|
||||||
self.inline_threshold = sess.opts.cg.inline_threshold;
|
self.inline_threshold = sess.opts.cg.inline_threshold;
|
||||||
self.new_llvm_pass_manager = sess.opts.debugging_opts.new_llvm_pass_manager;
|
self.new_llvm_pass_manager = sess.opts.debugging_opts.new_llvm_pass_manager;
|
||||||
self.obj_is_bitcode =
|
|
||||||
sess.target.target.options.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled();
|
|
||||||
self.embed_bitcode = if sess.opts.debugging_opts.embed_bitcode {
|
|
||||||
match sess.opts.optimize {
|
|
||||||
config::OptLevel::No | config::OptLevel::Less => EmbedBitcode::Marker,
|
|
||||||
_ => EmbedBitcode::Full,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
EmbedBitcode::None
|
|
||||||
};
|
|
||||||
|
|
||||||
// Copy what clang does by turning on loop vectorization at O2 and
|
// Copy what clang does by turning on loop vectorization at O2 and
|
||||||
// slp vectorization at O3. Otherwise configure other optimization aspects
|
// slp vectorization at O3. Otherwise configure other optimization aspects
|
||||||
@ -193,9 +196,9 @@ impl ModuleConfig {
|
|||||||
|
|
||||||
pub fn bitcode_needed(&self) -> bool {
|
pub fn bitcode_needed(&self) -> bool {
|
||||||
self.emit_bc
|
self.emit_bc
|
||||||
|| self.obj_is_bitcode
|
|
||||||
|| self.emit_bc_compressed
|
|| self.emit_bc_compressed
|
||||||
|| self.embed_bitcode == EmbedBitcode::Full
|
|| self.emit_obj == EmitObj::Bitcode
|
||||||
|
|| self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,6 +399,20 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
|
|||||||
allocator_config.emit_bc_compressed = true;
|
allocator_config.emit_bc_compressed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let emit_obj =
|
||||||
|
if sess.target.target.options.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled() {
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EmitObj::ObjectCode(BitcodeSection::None)
|
||||||
|
};
|
||||||
|
|
||||||
modules_config.emit_pre_lto_bc = need_pre_lto_bitcode_for_incr_comp(sess);
|
modules_config.emit_pre_lto_bc = need_pre_lto_bitcode_for_incr_comp(sess);
|
||||||
|
|
||||||
modules_config.no_integrated_as =
|
modules_config.no_integrated_as =
|
||||||
@ -415,20 +432,20 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
|
|||||||
// could be invoked specially with output_type_assembly, so
|
// could be invoked specially with output_type_assembly, so
|
||||||
// in this case we still want the metadata object file.
|
// in this case we still want the metadata object file.
|
||||||
if !sess.opts.output_types.contains_key(&OutputType::Assembly) {
|
if !sess.opts.output_types.contains_key(&OutputType::Assembly) {
|
||||||
metadata_config.emit_obj = true;
|
metadata_config.emit_obj = emit_obj;
|
||||||
allocator_config.emit_obj = true;
|
allocator_config.emit_obj = emit_obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OutputType::Object => {
|
OutputType::Object => {
|
||||||
modules_config.emit_obj = true;
|
modules_config.emit_obj = emit_obj;
|
||||||
}
|
}
|
||||||
OutputType::Metadata => {
|
OutputType::Metadata => {
|
||||||
metadata_config.emit_obj = true;
|
metadata_config.emit_obj = emit_obj;
|
||||||
}
|
}
|
||||||
OutputType::Exe => {
|
OutputType::Exe => {
|
||||||
modules_config.emit_obj = true;
|
modules_config.emit_obj = emit_obj;
|
||||||
metadata_config.emit_obj = true;
|
metadata_config.emit_obj = emit_obj;
|
||||||
allocator_config.emit_obj = true;
|
allocator_config.emit_obj = emit_obj;
|
||||||
}
|
}
|
||||||
OutputType::Mir => {}
|
OutputType::Mir => {}
|
||||||
OutputType::DepInfo => {}
|
OutputType::DepInfo => {}
|
||||||
@ -879,7 +896,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(object.is_some(), module_config.emit_obj);
|
assert_eq!(object.is_some(), module_config.emit_obj != EmitObj::None);
|
||||||
assert_eq!(bytecode.is_some(), module_config.emit_bc);
|
assert_eq!(bytecode.is_some(), module_config.emit_bc);
|
||||||
assert_eq!(bytecode_compressed.is_some(), module_config.emit_bc_compressed);
|
assert_eq!(bytecode_compressed.is_some(), module_config.emit_bc_compressed);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user