diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 5759eb2991a81..1557630fc7afd 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -16,7 +16,9 @@ use crate::ModuleLlvm; use log::debug; use rustc::bug; 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::{CompiledModule, ModuleCodegen, RLIB_BYTECODE_EXTENSION}; use rustc_data_structures::small_c_str::SmallCStr; @@ -651,7 +653,7 @@ pub(crate) unsafe fn codegen( let thin = ThinBuffer::new(llmod); 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( "LLVM_module_codegen_emit_bitcode", &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( "LLVM_module_codegen_embed_bitcode", &module.name[..], @@ -682,7 +684,7 @@ pub(crate) unsafe fn codegen( 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); } @@ -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 .prof .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]); @@ -743,60 +745,65 @@ pub(crate) unsafe fn codegen( // 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 // 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| { write_output_file(diag_handler, tm, cpm, llmod, &path, llvm::FileType::AssemblyFile) })?; } - if config_emit_normal_obj { - if !config.no_integrated_as { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]); - with_codegen(tm, llmod, config.no_builtins, |cpm| { - write_output_file( - diag_handler, - tm, - cpm, - llmod, - &obj_out, - llvm::FileType::ObjectFile, - ) - })?; - } else { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_module_codegen_asm_to_obj", &module.name[..]); - let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); - run_assembler(cgcx, diag_handler, &assembly, &obj_out); - - if !config.emit_asm && !cgcx.save_temps { - drop(fs::remove_file(&assembly)); + match config.emit_obj { + EmitObj::ObjectCode(_) => { + if !config.no_integrated_as { + let _timer = cgcx.prof.generic_activity_with_arg( + "LLVM_module_codegen_emit_obj", + &module.name[..], + ); + with_codegen(tm, llmod, config.no_builtins, |cpm| { + write_output_file( + diag_handler, + tm, + cpm, + llmod, + &obj_out, + llvm::FileType::ObjectFile, + ) + })?; + } else { + let _timer = cgcx.prof.generic_activity_with_arg( + "LLVM_module_codegen_asm_to_obj", + &module.name[..], + ); + let assembly = + cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + run_assembler(cgcx, diag_handler, &assembly, &obj_out); + + if !config.emit_asm && !cgcx.save_temps { + drop(fs::remove_file(&assembly)); + } } } - } - if config.obj_is_bitcode { - if config.emit_obj { + EmitObj::Bitcode => { 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 { - debug!("removing_bitcode {:?}", bc_out); - if let Err(e) = fs::remove_file(&bc_out) { - diag_handler.err(&format!("failed to remove bitcode: {}", e)); + if !config.emit_bc { + debug!("removing_bitcode {:?}", bc_out); + if let Err(e) = fs::remove_file(&bc_out) { + diag_handler.err(&format!("failed to remove bitcode: {}", e)); + } } } + + EmitObj::None => {} } drop(handlers); } Ok(module.into_compiled_module( - config.emit_obj, + config.emit_obj != EmitObj::None, config.emit_bc, config.emit_bc_compressed, &cgcx.output_filenames, diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index a4b5acdcd18a2..e9b3bf026b2ba 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -51,11 +51,31 @@ use std::thread; const PRE_LTO_BC_EXT: &str = "pre-lto.bc"; -/// The kind of bitcode to embed in object files. -#[derive(PartialEq)] -pub enum EmbedBitcode { +/// What kind of object file to emit. +#[derive(Clone, Copy, PartialEq)] +pub enum EmitObj { + // No object file. 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, + + // A full, uncompressed bitcode section. Full, } @@ -84,7 +104,7 @@ pub struct ModuleConfig { pub emit_bc_compressed: bool, pub emit_ir: bool, pub emit_asm: bool, - pub emit_obj: bool, + pub emit_obj: EmitObj, // Miscellaneous flags. These are mostly copied from command-line // options. pub verify_llvm_ir: bool, @@ -96,12 +116,7 @@ pub struct ModuleConfig { pub merge_functions: bool, pub inline_threshold: Option, pub new_llvm_pass_manager: Option, - // 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 embed_bitcode: EmbedBitcode, } impl ModuleConfig { @@ -124,9 +139,7 @@ impl ModuleConfig { emit_bc_compressed: false, emit_ir: false, emit_asm: false, - emit_obj: false, - obj_is_bitcode: false, - embed_bitcode: EmbedBitcode::None, + emit_obj: EmitObj::None, no_integrated_as: false, verify_llvm_ir: false, @@ -147,17 +160,6 @@ impl ModuleConfig { self.no_builtins = no_builtins || sess.target.target.options.no_builtins; self.inline_threshold = sess.opts.cg.inline_threshold; 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.target.target.options.embed_bitcode || 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 // slp vectorization at O3. Otherwise configure other optimization aspects @@ -194,9 +196,9 @@ impl ModuleConfig { pub fn bitcode_needed(&self) -> bool { self.emit_bc - || self.obj_is_bitcode || self.emit_bc_compressed - || self.embed_bitcode == EmbedBitcode::Full + || self.emit_obj == EmitObj::Bitcode + || self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) } } @@ -397,6 +399,20 @@ pub fn start_async_codegen( 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.no_integrated_as = @@ -416,20 +432,20 @@ pub fn start_async_codegen( // could be invoked specially with output_type_assembly, so // in this case we still want the metadata object file. if !sess.opts.output_types.contains_key(&OutputType::Assembly) { - metadata_config.emit_obj = true; - allocator_config.emit_obj = true; + metadata_config.emit_obj = emit_obj; + allocator_config.emit_obj = emit_obj; } } OutputType::Object => { - modules_config.emit_obj = true; + modules_config.emit_obj = emit_obj; } OutputType::Metadata => { - metadata_config.emit_obj = true; + metadata_config.emit_obj = emit_obj; } OutputType::Exe => { - modules_config.emit_obj = true; - metadata_config.emit_obj = true; - allocator_config.emit_obj = true; + modules_config.emit_obj = emit_obj; + metadata_config.emit_obj = emit_obj; + allocator_config.emit_obj = emit_obj; } OutputType::Mir => {} OutputType::DepInfo => {} @@ -880,7 +896,7 @@ fn execute_copy_from_cache_work_item( } } - 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_compressed.is_some(), module_config.emit_bc_compressed); diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 6e5111bd7018a..6d688c12977e3 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -771,9 +771,6 @@ pub struct TargetOptions { /// rather than "default" pub default_hidden_visibility: bool, - /// Whether or not bitcode is embedded in object files - pub embed_bitcode: bool, - /// Whether a .debug_gdb_scripts section will be added to the output object file pub emit_debug_gdb_scripts: bool, @@ -893,7 +890,6 @@ impl Default for TargetOptions { no_builtins: false, codegen_backend: "llvm".to_string(), default_hidden_visibility: false, - embed_bitcode: false, emit_debug_gdb_scripts: true, requires_uwtable: false, simd_types_indirect: true, @@ -1208,7 +1204,6 @@ impl Target { key!(no_builtins, bool); key!(codegen_backend); key!(default_hidden_visibility, bool); - key!(embed_bitcode, bool); key!(emit_debug_gdb_scripts, bool); key!(requires_uwtable, bool); key!(simd_types_indirect, bool); @@ -1437,7 +1432,6 @@ impl ToJson for Target { target_option_val!(no_builtins); target_option_val!(codegen_backend); target_option_val!(default_hidden_visibility); - target_option_val!(embed_bitcode); target_option_val!(emit_debug_gdb_scripts); target_option_val!(requires_uwtable); target_option_val!(simd_types_indirect);