rustc: Embed LLVM bitcode by default on iOS
This commit updates rustc to embed bitcode in each object file generated by default when compiling for iOS. This was determined in #35968 as a step towards better compatibility with the iOS toolchain, so let's give it a spin and see how it turns out! Note that this also updates the `cc` dependency which should propagate this change of embedding bitcode for C dependencies as well.
This commit is contained in:
parent
1999a3fb41
commit
0e0f74bcf9
4 changed files with 87 additions and 2 deletions
|
@ -1288,6 +1288,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
"run `dsymutil` and delete intermediate object files"),
|
||||
ui_testing: bool = (false, parse_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"),
|
||||
}
|
||||
|
||||
pub fn default_lib_output() -> CrateType {
|
||||
|
|
|
@ -473,6 +473,9 @@ pub struct TargetOptions {
|
|||
/// The default visibility for symbols in this target should be "hidden"
|
||||
/// rather than "default"
|
||||
pub default_hidden_visibility: bool,
|
||||
|
||||
/// Whether or not bitcode is embedded in object files
|
||||
pub embed_bitcode: bool,
|
||||
}
|
||||
|
||||
impl Default for TargetOptions {
|
||||
|
@ -544,6 +547,7 @@ impl Default for TargetOptions {
|
|||
i128_lowering: false,
|
||||
codegen_backend: "llvm".to_string(),
|
||||
default_hidden_visibility: false,
|
||||
embed_bitcode: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -792,6 +796,7 @@ impl Target {
|
|||
key!(no_builtins, bool);
|
||||
key!(codegen_backend);
|
||||
key!(default_hidden_visibility, bool);
|
||||
key!(embed_bitcode, bool);
|
||||
|
||||
if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
|
||||
for name in array.iter().filter_map(|abi| abi.as_string()) {
|
||||
|
@ -990,6 +995,7 @@ 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);
|
||||
|
||||
if default.abi_blacklist != self.options.abi_blacklist {
|
||||
d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
|
||||
|
|
|
@ -42,6 +42,7 @@ use syntax_pos::MultiSpan;
|
|||
use syntax_pos::symbol::Symbol;
|
||||
use type_::Type;
|
||||
use context::{is_pie_binary, get_reloc_model};
|
||||
use common::{C_bytes_in_context, val_ty};
|
||||
use jobserver::{Client, Acquired};
|
||||
use rustc_demangle;
|
||||
|
||||
|
@ -262,6 +263,8 @@ pub struct ModuleConfig {
|
|||
// emscripten's ecc compiler, when used as the linker.
|
||||
obj_is_bitcode: bool,
|
||||
no_integrated_as: bool,
|
||||
embed_bitcode: bool,
|
||||
embed_bitcode_marker: bool,
|
||||
}
|
||||
|
||||
impl ModuleConfig {
|
||||
|
@ -279,6 +282,8 @@ impl ModuleConfig {
|
|||
emit_asm: false,
|
||||
emit_obj: false,
|
||||
obj_is_bitcode: false,
|
||||
embed_bitcode: false,
|
||||
embed_bitcode_marker: false,
|
||||
no_integrated_as: false,
|
||||
|
||||
no_verify: false,
|
||||
|
@ -299,6 +304,17 @@ impl ModuleConfig {
|
|||
self.time_passes = sess.time_passes();
|
||||
self.inline_threshold = sess.opts.cg.inline_threshold;
|
||||
self.obj_is_bitcode = sess.target.target.options.obj_is_bitcode;
|
||||
let embed_bitcode = sess.target.target.options.embed_bitcode ||
|
||||
sess.opts.debugging_opts.embed_bitcode;
|
||||
if embed_bitcode {
|
||||
match sess.opts.optimize {
|
||||
config::OptLevel::No |
|
||||
config::OptLevel::Less => {
|
||||
self.embed_bitcode_marker = embed_bitcode;
|
||||
}
|
||||
_ => self.embed_bitcode = embed_bitcode,
|
||||
}
|
||||
}
|
||||
|
||||
// Copy what clang does by turning on loop vectorization at O2 and
|
||||
// slp vectorization at O3. Otherwise configure other optimization aspects
|
||||
|
@ -662,7 +678,7 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
|||
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
|
||||
|
||||
|
||||
if write_bc || config.emit_bc_compressed {
|
||||
if write_bc || config.emit_bc_compressed || config.embed_bitcode {
|
||||
let thin;
|
||||
let old;
|
||||
let data = if llvm::LLVMRustThinLTOAvailable() {
|
||||
|
@ -681,6 +697,11 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
|||
timeline.record("write-bc");
|
||||
}
|
||||
|
||||
if config.embed_bitcode {
|
||||
embed_bitcode(cgcx, llcx, llmod, Some(data));
|
||||
timeline.record("embed-bc");
|
||||
}
|
||||
|
||||
if config.emit_bc_compressed {
|
||||
let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
|
||||
let data = bytecode::encode(&mtrans.llmod_id, data);
|
||||
|
@ -689,6 +710,8 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
|||
}
|
||||
timeline.record("compress-bc");
|
||||
}
|
||||
} else if config.embed_bitcode_marker {
|
||||
embed_bitcode(cgcx, llcx, llmod, None);
|
||||
}
|
||||
|
||||
time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
|
||||
|
@ -796,6 +819,59 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
|||
&cgcx.output_filenames))
|
||||
}
|
||||
|
||||
/// 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:
|
||||
///
|
||||
/// * __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.
|
||||
///
|
||||
/// 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.
|
||||
unsafe fn embed_bitcode(cgcx: &CodegenContext,
|
||||
llcx: ContextRef,
|
||||
llmod: ModuleRef,
|
||||
bitcode: Option<&[u8]>) {
|
||||
let llconst = C_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
val_ty(llconst).to_ref(),
|
||||
"rustc.embedded.module\0".as_ptr() as *const _,
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
let section = if cgcx.opts.target_triple.contains("-ios") {
|
||||
"__LLVM,__bitcode\0"
|
||||
} else {
|
||||
".llvmbc\0"
|
||||
};
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _);
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
|
||||
let llconst = C_bytes_in_context(llcx, &[]);
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
val_ty(llconst).to_ref(),
|
||||
"rustc.embedded.cmdline\0".as_ptr() as *const _,
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
let section = if cgcx.opts.target_triple.contains("-ios") {
|
||||
"__LLVM,__cmdline\0"
|
||||
} else {
|
||||
".llvmcmd\0"
|
||||
};
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _);
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
}
|
||||
|
||||
pub(crate) struct CompiledModules {
|
||||
pub modules: Vec<CompiledModule>,
|
||||
pub metadata_module: CompiledModule,
|
||||
|
|
|
@ -86,6 +86,7 @@ fn main() {
|
|||
|
||||
fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
|
||||
let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?;
|
||||
let cflags = env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden -O2";
|
||||
|
||||
run(Command::new("sh")
|
||||
.current_dir(&native.out_dir)
|
||||
|
@ -98,7 +99,7 @@ fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
|
|||
.arg("--disable-host-shared")
|
||||
.arg(format!("--host={}", build_helper::gnu_target(target)))
|
||||
.arg(format!("--build={}", build_helper::gnu_target(host)))
|
||||
.env("CFLAGS", env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden -O2"));
|
||||
.env("CFLAGS", cflags));
|
||||
|
||||
run(Command::new(build_helper::make(host))
|
||||
.current_dir(&native.out_dir)
|
||||
|
|
Loading…
Add table
Reference in a new issue