@@ -26,6 +26,9 @@ use errors::emitter::Emitter;
2626use syntax_pos:: MultiSpan ;
2727use context:: { is_pie_binary, get_reloc_model} ;
2828
29+ use std:: ascii;
30+ use std:: char;
31+ use std:: process:: Command ;
2932use std:: ffi:: { CStr , CString } ;
3033use std:: fs;
3134use std:: path:: { Path , PathBuf } ;
@@ -262,6 +265,9 @@ pub struct ModuleConfig {
262265 // make the object file bitcode. Provides easy compatibility with
263266 // emscripten's ecc compiler, when used as the linker.
264267 obj_is_bitcode : bool ,
268+ // LLVM can't produce object files for MSP430. Instead, we'll make LLVM emit
269+ // assembly and then use `msp430-as` to turn that assembly into an object file
270+ obj_needs_as : bool ,
265271}
266272
267273unsafe impl Send for ModuleConfig { }
@@ -281,6 +287,7 @@ impl ModuleConfig {
281287 emit_asm : false ,
282288 emit_obj : false ,
283289 obj_is_bitcode : false ,
290+ obj_needs_as : false ,
284291
285292 no_verify : false ,
286293 no_prepopulate_passes : false ,
@@ -300,6 +307,7 @@ impl ModuleConfig {
300307 self . time_passes = sess. time_passes ( ) ;
301308 self . inline_threshold = sess. opts . cg . inline_threshold ;
302309 self . obj_is_bitcode = sess. target . target . options . obj_is_bitcode ;
310+ self . obj_needs_as = sess. target . target . options . obj_needs_as ;
303311
304312 // Copy what clang does by turning on loop vectorization at O2 and
305313 // slp vectorization at O3. Otherwise configure other optimization aspects
@@ -557,10 +565,13 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
557565 // machine code, instead copy the .o file from the .bc
558566 let write_bc = config. emit_bc || config. obj_is_bitcode ;
559567 let rm_bc = !config. emit_bc && config. obj_is_bitcode ;
568+ let write_asm = config. emit_asm || config. obj_needs_as ;
569+ let rm_asm = !config. emit_obj && config. obj_needs_as ;
560570 let write_obj = config. emit_obj && !config. obj_is_bitcode ;
561571 let copy_bc_to_obj = config. emit_obj && config. obj_is_bitcode ;
562572
563573 let bc_out = output_names. temp_path ( OutputType :: Bitcode , module_name) ;
574+ let asm_out = output_names. temp_path ( OutputType :: Assembly , module_name) ;
564575 let obj_out = output_names. temp_path ( OutputType :: Object , module_name) ;
565576
566577 if write_bc {
@@ -578,27 +589,25 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
578589 } )
579590 }
580591
581- if config. emit_asm {
582- let path = output_names. temp_path ( OutputType :: Assembly , module_name) ;
583-
592+ if write_asm {
584593 // We can't use the same module for asm and binary output, because that triggers
585594 // various errors like invalid IR or broken binaries, so we might have to clone the
586595 // module to produce the asm output
587- let llmod = if config. emit_obj {
596+ let llmod = if config. emit_obj && !config . obj_needs_as {
588597 llvm:: LLVMCloneModule ( llmod)
589598 } else {
590599 llmod
591600 } ;
592601 with_codegen ( tm, llmod, config. no_builtins , |cpm| {
593- write_output_file ( cgcx. handler , tm, cpm, llmod, & path ,
602+ write_output_file ( cgcx. handler , tm, cpm, llmod, & asm_out ,
594603 llvm:: FileType :: AssemblyFile ) ;
595604 } ) ;
596- if config. emit_obj {
605+ if config. emit_obj && !config . obj_needs_as {
597606 llvm:: LLVMDisposeModule ( llmod) ;
598607 }
599608 }
600609
601- if write_obj {
610+ if write_obj && !config . obj_needs_as {
602611 with_codegen ( tm, llmod, config. no_builtins , |cpm| {
603612 write_output_file ( cgcx. handler , tm, cpm, llmod, & obj_out,
604613 llvm:: FileType :: ObjectFile ) ;
@@ -613,13 +622,73 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
613622 }
614623 }
615624
625+ if config. obj_needs_as {
626+ // XXX most of the logic here has been copied from the link_natively
627+ // function (src/librustc_trans/back/link.rs)
628+ // TODO don't hardcode, maybe expose as a `as` field in the target
629+ // specification
630+ // TODO how to properly access `sess` here?
631+ let mut cmd = Command :: new ( "msp430-as" ) ;
632+ cmd. arg ( "-o" ) ;
633+ cmd. arg ( obj_out) ;
634+ cmd. arg ( & asm_out) ;
635+
636+ info ! ( "{:?}" , & cmd) ;
637+ // let prog = time(sess.time_passes(), "running assembler",
638+ // || cmd.output());
639+ let prog = cmd. output ( ) ;
640+ match prog {
641+ Ok ( prog) => {
642+ fn escape_string ( s : & [ u8 ] ) -> String {
643+ str:: from_utf8 ( s) . map ( |s| s. to_owned ( ) )
644+ . unwrap_or_else ( |_| {
645+ let mut x = "Non-UTF-8 output: " . to_string ( ) ;
646+ x. extend ( s. iter ( )
647+ . flat_map ( |& b| ascii:: escape_default ( b) )
648+ . map ( |b| char:: from_u32 ( b as u32 ) . unwrap ( ) ) ) ;
649+ x
650+ } )
651+ }
652+ if !prog. status . success ( ) {
653+ let mut output = prog. stderr . clone ( ) ;
654+ output. extend_from_slice ( & prog. stdout ) ;
655+ // sess.struct_err(&format!("assembling with `msp430-as` failed: {}",
656+ // prog.status))
657+ // .note(&format!("{:?}", &cmd))
658+ // .note(&escape_string(&output[..]))
659+ // .emit();
660+ // sess.abort_if_errors();
661+ }
662+ info ! ( "linker stderr:\n {}" , escape_string( & prog. stderr[ ..] ) ) ;
663+ info ! ( "linker stdout:\n {}" , escape_string( & prog. stdout[ ..] ) ) ;
664+ } ,
665+ Err ( _) => {
666+ // sess.struct_err(&format!("could not exec the assembler `msp430-as`: {}", e))
667+ // .note(&format!("{:?}", &cmd))
668+ // .emit();
669+ // if e.kind() == io::ErrorKind::NotFound {
670+ // sess.note_without_error("MSP430 targets depend on the MSP430 assembler \
671+ // but `msp430-as` was not found");
672+ // }
673+ // sess.abort_if_errors();
674+ } ,
675+ }
676+ }
677+
616678 if rm_bc {
617679 debug ! ( "removing_bitcode {:?}" , bc_out) ;
618680 if let Err ( e) = fs:: remove_file ( & bc_out) {
619681 cgcx. handler . err ( & format ! ( "failed to remove bitcode: {}" , e) ) ;
620682 }
621683 }
622684
685+ if rm_asm {
686+ debug ! ( "removing_assembly {:?}" , bc_out) ;
687+ if let Err ( e) = fs:: remove_file ( & asm_out) {
688+ cgcx. handler . err ( & format ! ( "failed to remove assembly: {}" , e) ) ;
689+ }
690+ }
691+
623692 llvm:: LLVMRustDisposeTargetMachine ( tm) ;
624693}
625694
0 commit comments