diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 394e2f332cb21..e261ac6544679 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -651,10 +651,8 @@ pub(crate) unsafe fn codegen( "LLVM_module_codegen_embed_bitcode", &module.name[..], ); - embed_bitcode(cgcx, llcx, llmod, Some(data)); + embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); } - } else if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Marker) { - embed_bitcode(cgcx, llcx, llmod, None); } if config.emit_ir { @@ -777,8 +775,8 @@ pub(crate) unsafe fn codegen( /// * __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. +/// recognize what's going on. A suitable cmdline value is taken from the +/// target spec. /// /// Furthermore debug/O1 builds don't actually embed bitcode but rather just /// embed an empty section. @@ -789,9 +787,10 @@ unsafe fn embed_bitcode( cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module, - bitcode: Option<&[u8]>, + cmdline: &str, + 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), @@ -800,14 +799,15 @@ unsafe fn embed_bitcode( llvm::LLVMSetInitializer(llglobal, llconst); let is_apple = cgcx.opts.target_triple.triple().contains("-ios") - || cgcx.opts.target_triple.triple().contains("-darwin"); + || cgcx.opts.target_triple.triple().contains("-darwin") + || cgcx.opts.target_triple.triple().contains("-tvos"); let section = if is_apple { "__LLVM,__bitcode\0" } else { ".llvmbc\0" }; llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); llvm::LLVMSetGlobalConstant(llglobal, llvm::True); - let llconst = common::bytes_in_context(llcx, &[]); + let llconst = common::bytes_in_context(llcx, cmdline.as_bytes()); 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 5c3444eff0a11..21eb56f12b971 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -68,10 +68,6 @@ 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, } @@ -101,6 +97,7 @@ pub struct ModuleConfig { pub emit_ir: bool, pub emit_asm: bool, pub emit_obj: EmitObj, + pub bc_cmdline: String, // Miscellaneous flags. These are mostly copied from command-line // options. @@ -147,14 +144,8 @@ impl ModuleConfig { || sess.opts.cg.linker_plugin_lto.enabled() { EmitObj::Bitcode - } else if need_crate_bitcode_for_rlib(sess) { - let force_full = need_crate_bitcode_for_rlib(sess); - match sess.opts.optimize { - config::OptLevel::No | config::OptLevel::Less if !force_full => { - EmitObj::ObjectCode(BitcodeSection::Marker) - } - _ => EmitObj::ObjectCode(BitcodeSection::Full), - } + } else if need_bitcode_in_object(sess) { + EmitObj::ObjectCode(BitcodeSection::Full) } else { EmitObj::ObjectCode(BitcodeSection::None) }; @@ -211,6 +202,7 @@ impl ModuleConfig { false ), emit_obj, + bc_cmdline: sess.target.target.options.bitcode_llvm_cmdline.clone(), verify_llvm_ir: sess.verify_llvm_ir(), no_prepopulate_passes: sess.opts.cg.no_prepopulate_passes, @@ -372,10 +364,12 @@ pub struct CompiledModules { pub allocator_module: Option, } -fn need_crate_bitcode_for_rlib(sess: &Session) -> bool { - sess.opts.cg.embed_bitcode +fn need_bitcode_in_object(sess: &Session) -> bool { + let requested_for_rlib = sess.opts.cg.embed_bitcode && sess.crate_types.borrow().contains(&CrateType::Rlib) - && sess.opts.output_types.contains_key(&OutputType::Exe) + && sess.opts.output_types.contains_key(&OutputType::Exe); + let forced_by_target = sess.target.target.options.forces_embed_bitcode; + requested_for_rlib || forced_by_target } fn need_pre_lto_bitcode_for_incr_comp(sess: &Session) -> bool { diff --git a/src/librustc_target/spec/aarch64_apple_ios.rs b/src/librustc_target/spec/aarch64_apple_ios.rs index e896b46da9a62..eac2c3e6aa40c 100644 --- a/src/librustc_target/spec/aarch64_apple_ios.rs +++ b/src/librustc_target/spec/aarch64_apple_ios.rs @@ -19,6 +19,18 @@ pub fn target() -> TargetResult { eliminate_frame_pointer: false, max_atomic_width: Some(128), abi_blacklist: super::arm_base::abi_blacklist(), + forces_embed_bitcode: true, + // Taken from a clang build on Xcode 11.4.1. + // These arguments are not actually invoked - they just have + // to look right to pass App Store validation. + bitcode_llvm_cmdline: "-triple\0\ + arm64-apple-ios11.0.0\0\ + -emit-obj\0\ + -disable-llvm-passes\0\ + -target-abi\0\ + darwinpcs\0\ + -Os\0" + .to_string(), ..base }, }) diff --git a/src/librustc_target/spec/aarch64_apple_tvos.rs b/src/librustc_target/spec/aarch64_apple_tvos.rs index 794bc7900e747..f1cd14ffd11a6 100644 --- a/src/librustc_target/spec/aarch64_apple_tvos.rs +++ b/src/librustc_target/spec/aarch64_apple_tvos.rs @@ -19,6 +19,7 @@ pub fn target() -> TargetResult { eliminate_frame_pointer: false, max_atomic_width: Some(128), abi_blacklist: super::arm_base::abi_blacklist(), + forces_embed_bitcode: true, ..base }, }) diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index e853c07632f90..51dce9e144caa 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -783,6 +783,10 @@ pub struct TargetOptions { // If we give emcc .o files that are actually .bc files it // will 'just work'. pub obj_is_bitcode: bool, + /// Whether the target requires that emitted object code includes bitcode. + pub forces_embed_bitcode: bool, + /// Content of the LLVM cmdline section associated with embedded bitcode. + pub bitcode_llvm_cmdline: String, /// Don't use this field; instead use the `.min_atomic_width()` method. pub min_atomic_width: Option, @@ -939,6 +943,8 @@ impl Default for TargetOptions { allow_asm: true, has_elf_tls: false, obj_is_bitcode: false, + forces_embed_bitcode: false, + bitcode_llvm_cmdline: String::new(), min_atomic_width: None, max_atomic_width: None, atomic_cas: true, @@ -1278,6 +1284,8 @@ impl Target { key!(main_needs_argc_argv, bool); key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); + key!(forces_embed_bitcode, bool); + key!(bitcode_llvm_cmdline); key!(max_atomic_width, Option); key!(min_atomic_width, Option); key!(atomic_cas, bool); @@ -1505,6 +1513,8 @@ impl ToJson for Target { target_option_val!(main_needs_argc_argv); target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); + target_option_val!(forces_embed_bitcode); + target_option_val!(bitcode_llvm_cmdline); target_option_val!(min_atomic_width); target_option_val!(max_atomic_width); target_option_val!(atomic_cas);