Skip to content

Commit

Permalink
Provide configurable LLVM cmdline section via target spec
Browse files Browse the repository at this point in the history
The App Store performs certain sanity checks on bitcode, including that
an acceptable set of command line arguments was used when compiling a
given module. For Rust code to be distributed on the app store with
bitcode rustc must pretend to have the same command line arguments.
  • Loading branch information
thombles committed May 7, 2020
1 parent 342aad1 commit a390803
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 6 deletions.
14 changes: 8 additions & 6 deletions src/librustc_codegen_llvm/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,10 +651,10 @@ 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, Some(data));
}
} else if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Marker) {
embed_bitcode(cgcx, llcx, llmod, None);
embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, None);
}

if config.emit_ir {
Expand Down Expand Up @@ -777,8 +777,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.
Expand All @@ -789,6 +789,7 @@ unsafe fn embed_bitcode(
cgcx: &CodegenContext<LlvmCodegenBackend>,
llcx: &llvm::Context,
llmod: &llvm::Module,
cmdline: &str,
bitcode: Option<&[u8]>,
) {
let llconst = common::bytes_in_context(llcx, bitcode.unwrap_or(&[]));
Expand All @@ -800,14 +801,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),
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_codegen_ssa/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,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.
Expand Down Expand Up @@ -213,6 +214,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,
Expand Down
11 changes: 11 additions & 0 deletions src/librustc_target/spec/aarch64_apple_ios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@ pub fn target() -> TargetResult {
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
},
})
Expand Down
5 changes: 5 additions & 0 deletions src/librustc_target/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,8 @@ pub struct TargetOptions {
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<u64>,
Expand Down Expand Up @@ -942,6 +944,7 @@ impl Default for TargetOptions {
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,
Expand Down Expand Up @@ -1282,6 +1285,7 @@ impl Target {
key!(has_elf_tls, bool);
key!(obj_is_bitcode, bool);
key!(forces_embed_bitcode, bool);
key!(bitcode_llvm_cmdline);
key!(max_atomic_width, Option<u64>);
key!(min_atomic_width, Option<u64>);
key!(atomic_cas, bool);
Expand Down Expand Up @@ -1510,6 +1514,7 @@ impl ToJson for Target {
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);
Expand Down

0 comments on commit a390803

Please sign in to comment.