rustc: Add obj_is_bitcode to TargetOptions

This tells trans:🔙:write not to LLVM codegen to create .o
files but to put LLMV bitcode in .o files.

Emscripten's emcc supports .o in this format, and this is,
I think, slightly easier than making rlibs work without .o
files.
This commit is contained in:
Brian Anderson 2015-11-27 19:44:33 +00:00
parent d6c0d859f6
commit 81ba4a78b5
3 changed files with 44 additions and 10 deletions

View file

@ -22,6 +22,7 @@ pub fn target() -> Target {
linker_is_gnu: true,
allow_asm: false,
archive_format: "gnu".to_string(),
obj_is_bitcode: true,
.. Default::default()
};
Target {

View file

@ -204,6 +204,10 @@ pub struct TargetOptions {
/// Flag indicating whether ELF TLS (e.g. #[thread_local]) is available for
/// this target.
pub has_elf_tls: bool,
// This is mainly for easy compatibility with emscripten.
// If we give emcc .o files that are actually .bc files it
// will 'just work'.
pub obj_is_bitcode: bool,
}
impl Default for TargetOptions {
@ -251,6 +255,7 @@ impl Default for TargetOptions {
exe_allocation_crate: "alloc_system".to_string(),
allow_asm: true,
has_elf_tls: false,
obj_is_bitcode: false,
}
}
}

View file

@ -244,7 +244,6 @@ pub struct ModuleConfig {
emit_ir: bool,
emit_asm: bool,
emit_obj: bool,
// Miscellaneous flags. These are mostly copied from command-line
// options.
no_verify: bool,
@ -254,7 +253,11 @@ pub struct ModuleConfig {
vectorize_loop: bool,
vectorize_slp: bool,
merge_functions: bool,
inline_threshold: Option<usize>
inline_threshold: Option<usize>,
// 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.
obj_is_bitcode: bool,
}
unsafe impl Send for ModuleConfig { }
@ -272,6 +275,7 @@ impl ModuleConfig {
emit_ir: false,
emit_asm: false,
emit_obj: false,
obj_is_bitcode: false,
no_verify: false,
no_prepopulate_passes: false,
@ -290,6 +294,7 @@ impl ModuleConfig {
self.no_builtins = trans.no_builtins;
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;
// Copy what clang does by turning on loop vectorization at O2 and
// slp vectorization at O3. Otherwise configure other optimization aspects
@ -530,11 +535,21 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
f(cpm);
}
if config.emit_bc {
let ext = format!("{}.bc", name_extra);
let out = output_names.with_extension(&ext);
let out = path2cstr(&out);
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
// Change what we write and cleanup based on whether obj files are
// just llvm bitcode. In that case write bitcode, and possibly
// delete the bitcode if it wasn't requested. Don't generate the
// machine code, instead copy the .o file from the .bc
let write_bc = config.emit_bc || config.obj_is_bitcode;
let rm_bc = !config.emit_bc && config.obj_is_bitcode;
let write_obj = config.emit_obj && !config.obj_is_bitcode;
let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
let bc_out = output_names.with_extension(&format!("{}.bc", name_extra));
let obj_out = output_names.with_extension(&format!("{}.o", name_extra));
if write_bc {
let bc_out_c = path2cstr(&bc_out);
llvm::LLVMWriteBitcodeToFile(llmod, bc_out_c.as_ptr());
}
time(config.time_passes, &format!("codegen passes [{}]", cgcx.worker), || {
@ -568,14 +583,27 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
}
}
if config.emit_obj {
let path = output_names.with_extension(&format!("{}.o", name_extra));
if write_obj {
with_codegen(tm, llmod, config.no_builtins, |cpm| {
write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::ObjectFileType);
write_output_file(cgcx.handler, tm, cpm, llmod, &obj_out, llvm::ObjectFileType);
});
}
});
if copy_bc_to_obj {
debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
if let Err(e) = fs::copy(&bc_out, &obj_out) {
cgcx.handler.err(&format!("failed to copy bitcode to object file: {}", e));
}
}
if rm_bc {
debug!("removing_bitcode {:?}", bc_out);
if let Err(e) = fs::remove_file(&bc_out) {
cgcx.handler.err(&format!("failed to remove bitcode: {}", e));
}
}
llvm::LLVMDisposeModule(llmod);
llvm::LLVMContextDispose(llcx);
llvm::LLVMRustDisposeTargetMachine(tm);