Skip to content

Commit fcde990

Browse files
author
Jorge Aparicio
committed
use msp430-as to emit object files from the assembly that LLVM emits
1 parent 7b55936 commit fcde990

File tree

2 files changed

+83
-7
lines changed

2 files changed

+83
-7
lines changed

src/librustc_back/target/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,10 @@ pub struct TargetOptions {
359359
// will 'just work'.
360360
pub obj_is_bitcode: bool,
361361

362+
// LLVM can't produce object files for MSP430. Instead, we'll make LLVM emit
363+
// assembly and then use `msp430-as` to turn that assembly into an object file
364+
pub obj_needs_as: bool,
365+
362366
/// Don't use this field; instead use the `.max_atomic_width()` method.
363367
pub max_atomic_width: Option<u64>,
364368

@@ -416,6 +420,7 @@ impl Default for TargetOptions {
416420
allow_asm: true,
417421
has_elf_tls: false,
418422
obj_is_bitcode: false,
423+
obj_needs_as: false,
419424
max_atomic_width: None,
420425
panic_strategy: PanicStrategy::Unwind,
421426
abi_blacklist: vec![],
@@ -576,6 +581,7 @@ impl Target {
576581
key!(exe_allocation_crate);
577582
key!(has_elf_tls, bool);
578583
key!(obj_is_bitcode, bool);
584+
key!(obj_needs_as, bool);
579585
key!(max_atomic_width, Option<u64>);
580586
try!(key!(panic_strategy, PanicStrategy));
581587

@@ -735,6 +741,7 @@ impl ToJson for Target {
735741
target_option_val!(exe_allocation_crate);
736742
target_option_val!(has_elf_tls);
737743
target_option_val!(obj_is_bitcode);
744+
target_option_val!(obj_needs_as);
738745
target_option_val!(max_atomic_width);
739746
target_option_val!(panic_strategy);
740747

src/librustc_trans/back/write.rs

+76-7
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ use errors::emitter::Emitter;
2626
use syntax_pos::MultiSpan;
2727
use context::{is_pie_binary, get_reloc_model};
2828

29+
use std::ascii;
30+
use std::char;
31+
use std::process::Command;
2932
use std::ffi::{CStr, CString};
3033
use std::fs;
3134
use 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

267273
unsafe 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

Comments
 (0)