diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index f6a0946dd5b8e..cc04582b19e28 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -359,9 +359,10 @@ pub struct TargetOptions { // will 'just work'. pub obj_is_bitcode: bool, - // LLVM can't produce object files for MSP430. Instead, we'll make LLVM emit - // assembly and then use `msp430-as` to turn that assembly into an object file - pub obj_needs_as: bool, + // LLVM can't produce object files for this target. Instead, we'll make LLVM + // emit assembly and then use `gcc` to turn that assembly into an object + // file + pub no_integrated_as: bool, /// Don't use this field; instead use the `.max_atomic_width()` method. pub max_atomic_width: Option, @@ -420,7 +421,7 @@ impl Default for TargetOptions { allow_asm: true, has_elf_tls: false, obj_is_bitcode: false, - obj_needs_as: false, + no_integrated_as: false, max_atomic_width: None, panic_strategy: PanicStrategy::Unwind, abi_blacklist: vec![], @@ -581,7 +582,7 @@ impl Target { key!(exe_allocation_crate); key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); - key!(obj_needs_as, bool); + key!(no_integrated_as, bool); key!(max_atomic_width, Option); try!(key!(panic_strategy, PanicStrategy)); @@ -741,7 +742,7 @@ impl ToJson for Target { target_option_val!(exe_allocation_crate); target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); - target_option_val!(obj_needs_as); + target_option_val!(no_integrated_as); target_option_val!(max_atomic_width); target_option_val!(panic_strategy); diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index d83918495676c..48bf490d685b1 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1056,7 +1056,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn phase_5_run_llvm_passes(sess: &Session, trans: &trans::CrateTranslation, outputs: &OutputFilenames) -> CompileResult { - if sess.opts.cg.no_integrated_as { + if sess.opts.cg.no_integrated_as || sess.target.target.options.no_integrated_as { let output_types = OutputTypes::new(&[(OutputType::Assembly, None)]); time(sess.time_passes(), "LLVM passes", @@ -1064,6 +1064,17 @@ pub fn phase_5_run_llvm_passes(sess: &Session, write::run_assembler(sess, outputs); + // HACK the linker expects the object file to be named foo.0.o but + // `run_assembler` produces an object named just foo.o. Rename it if we + // are going to build an executable + if sess.opts.output_types.contains_key(&OutputType::Exe) { + let f = outputs.path(OutputType::Object); + fs::copy(&f, + f.with_file_name(format!("{}.0.o", + f.file_stem().unwrap().to_string_lossy()))).unwrap(); + fs::remove_file(f).unwrap(); + } + // Remove assembly source, unless --save-temps was specified if !sess.opts.cg.save_temps { fs::remove_file(&outputs.temp_path(OutputType::Assembly, None)).unwrap(); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 0af7c66ccd42a..9012914deeb09 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -26,9 +26,6 @@ use errors::emitter::Emitter; use syntax_pos::MultiSpan; use context::{is_pie_binary, get_reloc_model}; -use std::ascii; -use std::char; -use std::process::Command; use std::ffi::{CStr, CString}; use std::fs; use std::path::{Path, PathBuf}; @@ -265,9 +262,6 @@ pub struct ModuleConfig { // make the object file bitcode. Provides easy compatibility with // emscripten's ecc compiler, when used as the linker. obj_is_bitcode: bool, - // LLVM can't produce object files for MSP430. Instead, we'll make LLVM emit - // assembly and then use `msp430-as` to turn that assembly into an object file - obj_needs_as: bool, } unsafe impl Send for ModuleConfig { } @@ -287,7 +281,6 @@ impl ModuleConfig { emit_asm: false, emit_obj: false, obj_is_bitcode: false, - obj_needs_as: false, no_verify: false, no_prepopulate_passes: false, @@ -307,7 +300,6 @@ 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; - self.obj_needs_as = sess.target.target.options.obj_needs_as; // Copy what clang does by turning on loop vectorization at O2 and // slp vectorization at O3. Otherwise configure other optimization aspects @@ -565,13 +557,10 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, // 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_asm = config.emit_asm || config.obj_needs_as; - let rm_asm = !config.emit_obj && config.obj_needs_as; 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.temp_path(OutputType::Bitcode, module_name); - let asm_out = output_names.temp_path(OutputType::Assembly, module_name); let obj_out = output_names.temp_path(OutputType::Object, module_name); if write_bc { @@ -589,25 +578,27 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, }) } - if write_asm { + if config.emit_asm { + let path = output_names.temp_path(OutputType::Assembly, module_name); + // 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 && !config.obj_needs_as { + let llmod = if config.emit_obj { llvm::LLVMCloneModule(llmod) } else { llmod }; with_codegen(tm, llmod, config.no_builtins, |cpm| { - write_output_file(cgcx.handler, tm, cpm, llmod, &asm_out, + write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::FileType::AssemblyFile); }); - if config.emit_obj && !config.obj_needs_as { + if config.emit_obj { llvm::LLVMDisposeModule(llmod); } } - if write_obj && !config.obj_needs_as { + if write_obj { with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file(cgcx.handler, tm, cpm, llmod, &obj_out, llvm::FileType::ObjectFile); @@ -622,59 +613,6 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, } } - if config.obj_needs_as { - // XXX most of the logic here has been copied from the link_natively - // function (src/librustc_trans/back/link.rs) - // TODO don't hardcode, maybe expose as a `as` field in the target - // specification - // TODO how to properly access `sess` here? - let mut cmd = Command::new("msp430-as"); - cmd.arg("-o"); - cmd.arg(obj_out); - cmd.arg(&asm_out); - - info!("{:?}", &cmd); - // let prog = time(sess.time_passes(), "running assembler", - // || cmd.output()); - let prog = cmd.output(); - match prog { - Ok(prog) => { - fn escape_string(s: &[u8]) -> String { - str::from_utf8(s).map(|s| s.to_owned()) - .unwrap_or_else(|_| { - let mut x = "Non-UTF-8 output: ".to_string(); - x.extend(s.iter() - .flat_map(|&b| ascii::escape_default(b)) - .map(|b| char::from_u32(b as u32).unwrap())); - x - }) - } - if !prog.status.success() { - let mut output = prog.stderr.clone(); - output.extend_from_slice(&prog.stdout); - // sess.struct_err(&format!("assembling with `msp430-as` failed: {}", - // prog.status)) - // .note(&format!("{:?}", &cmd)) - // .note(&escape_string(&output[..])) - // .emit(); - // sess.abort_if_errors(); - } - info!("linker stderr:\n{}", escape_string(&prog.stderr[..])); - info!("linker stdout:\n{}", escape_string(&prog.stdout[..])); - }, - Err(_) => { - // sess.struct_err(&format!("could not exec the assembler `msp430-as`: {}", e)) - // .note(&format!("{:?}", &cmd)) - // .emit(); - // if e.kind() == io::ErrorKind::NotFound { - // sess.note_without_error("MSP430 targets depend on the MSP430 assembler \ - // but `msp430-as` was not found"); - // } - // sess.abort_if_errors(); - }, - } - } - if rm_bc { debug!("removing_bitcode {:?}", bc_out); if let Err(e) = fs::remove_file(&bc_out) { @@ -682,13 +620,6 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, } } - if rm_asm { - debug!("removing_assembly {:?}", bc_out); - if let Err(e) = fs::remove_file(&asm_out) { - cgcx.handler.err(&format!("failed to remove assembly: {}", e)); - } - } - llvm::LLVMRustDisposeTargetMachine(tm); }