@@ -26,6 +26,9 @@ use errors::emitter::Emitter;
26
26
use syntax_pos:: MultiSpan ;
27
27
use context:: { is_pie_binary, get_reloc_model} ;
28
28
29
+ use std:: ascii;
30
+ use std:: char;
31
+ use std:: process:: Command ;
29
32
use std:: ffi:: { CStr , CString } ;
30
33
use std:: fs;
31
34
use std:: path:: { Path , PathBuf } ;
@@ -262,6 +265,9 @@ pub struct ModuleConfig {
262
265
// make the object file bitcode. Provides easy compatibility with
263
266
// emscripten's ecc compiler, when used as the linker.
264
267
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 ,
265
271
}
266
272
267
273
unsafe impl Send for ModuleConfig { }
@@ -281,6 +287,7 @@ impl ModuleConfig {
281
287
emit_asm : false ,
282
288
emit_obj : false ,
283
289
obj_is_bitcode : false ,
290
+ obj_needs_as : false ,
284
291
285
292
no_verify : false ,
286
293
no_prepopulate_passes : false ,
@@ -300,6 +307,7 @@ impl ModuleConfig {
300
307
self . time_passes = sess. time_passes ( ) ;
301
308
self . inline_threshold = sess. opts . cg . inline_threshold ;
302
309
self . obj_is_bitcode = sess. target . target . options . obj_is_bitcode ;
310
+ self . obj_needs_as = sess. target . target . options . obj_needs_as ;
303
311
304
312
// Copy what clang does by turning on loop vectorization at O2 and
305
313
// slp vectorization at O3. Otherwise configure other optimization aspects
@@ -557,10 +565,13 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
557
565
// machine code, instead copy the .o file from the .bc
558
566
let write_bc = config. emit_bc || config. obj_is_bitcode ;
559
567
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 ;
560
570
let write_obj = config. emit_obj && !config. obj_is_bitcode ;
561
571
let copy_bc_to_obj = config. emit_obj && config. obj_is_bitcode ;
562
572
563
573
let bc_out = output_names. temp_path ( OutputType :: Bitcode , module_name) ;
574
+ let asm_out = output_names. temp_path ( OutputType :: Assembly , module_name) ;
564
575
let obj_out = output_names. temp_path ( OutputType :: Object , module_name) ;
565
576
566
577
if write_bc {
@@ -578,27 +589,25 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
578
589
} )
579
590
}
580
591
581
- if config. emit_asm {
582
- let path = output_names. temp_path ( OutputType :: Assembly , module_name) ;
583
-
592
+ if write_asm {
584
593
// We can't use the same module for asm and binary output, because that triggers
585
594
// various errors like invalid IR or broken binaries, so we might have to clone the
586
595
// module to produce the asm output
587
- let llmod = if config. emit_obj {
596
+ let llmod = if config. emit_obj && !config . obj_needs_as {
588
597
llvm:: LLVMCloneModule ( llmod)
589
598
} else {
590
599
llmod
591
600
} ;
592
601
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 ,
594
603
llvm:: FileType :: AssemblyFile ) ;
595
604
} ) ;
596
- if config. emit_obj {
605
+ if config. emit_obj && !config . obj_needs_as {
597
606
llvm:: LLVMDisposeModule ( llmod) ;
598
607
}
599
608
}
600
609
601
- if write_obj {
610
+ if write_obj && !config . obj_needs_as {
602
611
with_codegen ( tm, llmod, config. no_builtins , |cpm| {
603
612
write_output_file ( cgcx. handler , tm, cpm, llmod, & obj_out,
604
613
llvm:: FileType :: ObjectFile ) ;
@@ -613,13 +622,73 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
613
622
}
614
623
}
615
624
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
+
616
678
if rm_bc {
617
679
debug ! ( "removing_bitcode {:?}" , bc_out) ;
618
680
if let Err ( e) = fs:: remove_file ( & bc_out) {
619
681
cgcx. handler . err ( & format ! ( "failed to remove bitcode: {}" , e) ) ;
620
682
}
621
683
}
622
684
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
+
623
692
llvm:: LLVMRustDisposeTargetMachine ( tm) ;
624
693
}
625
694
0 commit comments