From f5a05adb25753e73107843fd010abc12c38841ee Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 9 Nov 2016 14:00:26 -0500 Subject: [PATCH 1/8] enable the MSP430 LLVM backend to let people experiment with this target out of tree. The MSP430 architecture is used in 16-bit microcontrollers commonly used in Digital Signal Processing applications. --- src/librustc_llvm/build.rs | 2 +- src/librustc_llvm/lib.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 8656bb8bf0036..ca80a5269c95a 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -66,7 +66,7 @@ fn main() { let is_crossed = target != host; let optional_components = - ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz", "jsbackend"]; + ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz", "jsbackend", "msp430"]; // FIXME: surely we don't need all these components, right? Stuff like mcjit // or interpreter the compiler itself never uses. diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 07b87072c435e..65e0dbcad3a6a 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -413,6 +413,11 @@ pub fn initialize_available_targets() { LLVMInitializeJSBackendTargetInfo, LLVMInitializeJSBackendTarget, LLVMInitializeJSBackendTargetMC); + init_target!(llvm_component = "msp430", + LLVMInitializeMSP430TargetInfo, + LLVMInitializeMSP430Target, + LLVMInitializeMSP430TargetMC, + LLVMInitializeMSP430AsmPrinter); } pub fn last_error() -> Option { From 30e5667607ca6eb6b6fb8fbe44c420a8de2ea749 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 9 Nov 2016 14:45:44 -0500 Subject: [PATCH 2/8] fix #37673 --- src/librustc_trans/mir/rvalue.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index f25877b1de12d..fc691649ae4ab 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -729,11 +729,13 @@ fn get_overflow_intrinsic(oop: OverflowOp, bcx: &BlockAndBuilder, ty: Ty) -> Val let new_sty = match ty.sty { TyInt(Is) => match &tcx.sess.target.target.target_pointer_width[..] { + "16" => TyInt(I16), "32" => TyInt(I32), "64" => TyInt(I64), _ => panic!("unsupported target word size") }, TyUint(Us) => match &tcx.sess.target.target.target_pointer_width[..] { + "16" => TyUint(U16), "32" => TyUint(U32), "64" => TyUint(U64), _ => panic!("unsupported target word size") From 4f9f7b014eecc940c06d0cc75f46f153c64c4d2d Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 9 Nov 2016 16:56:10 -0500 Subject: [PATCH 3/8] also enable the MSP430 backend in Makefiles --- configure | 2 +- mk/main.mk | 2 +- src/rustllvm/PassWrapper.cpp | 9 ++++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 9c055e7217aa3..16d6a90bf391d 100755 --- a/configure +++ b/configure @@ -1782,7 +1782,7 @@ do CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=ON" fi - CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend'" + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430'" CMAKE_ARGS="$CMAKE_ARGS -G '$CFG_CMAKE_GENERATOR'" CMAKE_ARGS="$CMAKE_ARGS $CFG_LLVM_SRC_DIR" diff --git a/mk/main.mk b/mk/main.mk index 07b52593781cf..9936c5b59be5c 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -285,7 +285,7 @@ endif # LLVM macros ###################################################################### -LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl systemz jsbackend +LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl systemz jsbackend msp430 LLVM_REQUIRED_COMPONENTS=ipo bitreader bitwriter linker asmparser mcjit \ interpreter instrumentation diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 60093e9bd37a8..a5ba1d219c369 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -137,13 +137,20 @@ LLVMRustAddPass(LLVMPassManagerRef PM, LLVMPassRef rust_pass) { #define SUBTARGET_SYSTEMZ #endif +#ifdef LLVM_COMPONENT_MSP430 +#define SUBTARGET_MSP430 SUBTARGET(MSP430) +#else +#define SUBTARGET_MSP430 +#endif + #define GEN_SUBTARGETS \ SUBTARGET_X86 \ SUBTARGET_ARM \ SUBTARGET_AARCH64 \ SUBTARGET_MIPS \ SUBTARGET_PPC \ - SUBTARGET_SYSTEMZ + SUBTARGET_SYSTEMZ \ + SUBTARGET_MSP430 #define SUBTARGET(x) namespace llvm { \ extern const SubtargetFeatureKV x##FeatureKV[]; \ From 7b559368699c1d4c0df1e3d813c8a84dba3118aa Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 9 Nov 2016 16:57:14 -0500 Subject: [PATCH 4/8] oops, forgot to commit a rustbuild related file --- src/bootstrap/native.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 358cfac742777..96d1b695dd707 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -79,7 +79,8 @@ pub fn llvm(build: &Build, target: &str) { .out_dir(&dst) .profile(profile) .define("LLVM_ENABLE_ASSERTIONS", assertions) - .define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend") + .define("LLVM_TARGETS_TO_BUILD", + "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430") .define("LLVM_INCLUDE_EXAMPLES", "OFF") .define("LLVM_INCLUDE_TESTS", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") From fcde9904dbe7c4426a72b39a49b892eadb5a8940 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 9 Nov 2016 19:05:32 -0500 Subject: [PATCH 5/8] use msp430-as to emit object files from the assembly that LLVM emits --- src/librustc_back/target/mod.rs | 7 +++ src/librustc_trans/back/write.rs | 83 +++++++++++++++++++++++++++++--- 2 files changed, 83 insertions(+), 7 deletions(-) diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 14fe02269d142..f6a0946dd5b8e 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -359,6 +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, + /// Don't use this field; instead use the `.max_atomic_width()` method. pub max_atomic_width: Option, @@ -416,6 +420,7 @@ impl Default for TargetOptions { allow_asm: true, has_elf_tls: false, obj_is_bitcode: false, + obj_needs_as: false, max_atomic_width: None, panic_strategy: PanicStrategy::Unwind, abi_blacklist: vec![], @@ -576,6 +581,7 @@ impl Target { key!(exe_allocation_crate); key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); + key!(obj_needs_as, bool); key!(max_atomic_width, Option); try!(key!(panic_strategy, PanicStrategy)); @@ -735,6 +741,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!(max_atomic_width); target_option_val!(panic_strategy); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 9012914deeb09..0af7c66ccd42a 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -26,6 +26,9 @@ 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}; @@ -262,6 +265,9 @@ 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 { } @@ -281,6 +287,7 @@ impl ModuleConfig { emit_asm: false, emit_obj: false, obj_is_bitcode: false, + obj_needs_as: false, no_verify: false, no_prepopulate_passes: false, @@ -300,6 +307,7 @@ 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 @@ -557,10 +565,13 @@ 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 { @@ -578,27 +589,25 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, }) } - if config.emit_asm { - let path = output_names.temp_path(OutputType::Assembly, module_name); - + if write_asm { // 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 { + let llmod = if config.emit_obj && !config.obj_needs_as { llvm::LLVMCloneModule(llmod) } else { llmod }; with_codegen(tm, llmod, config.no_builtins, |cpm| { - write_output_file(cgcx.handler, tm, cpm, llmod, &path, + write_output_file(cgcx.handler, tm, cpm, llmod, &asm_out, llvm::FileType::AssemblyFile); }); - if config.emit_obj { + if config.emit_obj && !config.obj_needs_as { llvm::LLVMDisposeModule(llmod); } } - if write_obj { + if write_obj && !config.obj_needs_as { with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file(cgcx.handler, tm, cpm, llmod, &obj_out, llvm::FileType::ObjectFile); @@ -613,6 +622,59 @@ 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) { @@ -620,6 +682,13 @@ 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); } From a6a247798619cf513fcab2421bade4dc99994e67 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 12 Nov 2016 17:30:06 -0500 Subject: [PATCH 6/8] use write::run_assembler --- src/librustc_back/target/mod.rs | 13 ++--- src/librustc_driver/driver.rs | 13 ++++- src/librustc_trans/back/write.rs | 83 +++----------------------------- 3 files changed, 26 insertions(+), 83 deletions(-) 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); } From e7cae415ea207732a199dbdd23fb2baee1946d63 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 13 Nov 2016 11:03:44 -0500 Subject: [PATCH 7/8] add cabi_msp430 --- src/librustc_trans/abi.rs | 2 ++ src/librustc_trans/cabi_msp430.rs | 59 +++++++++++++++++++++++++++++++ src/librustc_trans/lib.rs | 1 + 3 files changed, 62 insertions(+) create mode 100644 src/librustc_trans/cabi_msp430.rs diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 0a5b013c79ac2..f2e15a8973c91 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -24,6 +24,7 @@ use cabi_s390x; use cabi_mips; use cabi_mips64; use cabi_asmjs; +use cabi_msp430; use machine::{llalign_of_min, llsize_of, llsize_of_alloc}; use type_::Type; use type_of; @@ -520,6 +521,7 @@ impl FnType { "s390x" => cabi_s390x::compute_abi_info(ccx, self), "asmjs" => cabi_asmjs::compute_abi_info(ccx, self), "wasm32" => cabi_asmjs::compute_abi_info(ccx, self), + "msp430" => cabi_msp430::compute_abi_info(ccx, self), a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)) } diff --git a/src/librustc_trans/cabi_msp430.rs b/src/librustc_trans/cabi_msp430.rs new file mode 100644 index 0000000000000..aa90bb7ab753a --- /dev/null +++ b/src/librustc_trans/cabi_msp430.rs @@ -0,0 +1,59 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Reference: MSP430 Embedded Application Binary Interface +// http://www.ti.com/lit/an/slaa534/slaa534.pdf + +#![allow(non_upper_case_globals)] + +use llvm::Struct; + +use abi::{self, ArgType, FnType}; +use context::CrateContext; +use type_::Type; + +fn ty_size(ty: Type) -> usize { + abi::ty_size(ty, 2) +} + +// 3.5 Structures or Unions Passed and Returned by Reference +// +// "Structures (including classes) and unions larger than 32 bits are passed and +// returned by reference. To pass a structure or union by reference, the caller +// places its address in the appropriate location: either in a register or on +// the stack, according to its position in the argument list. (..)" +fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { + if ret.ty.kind() == Struct && ty_size(ret.ty) > 32 { + ret.make_indirect(ccx); + } else { + ret.extend_integer_width_to(16); + } +} + +fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) { + if arg.ty.kind() == Struct && ty_size(arg.ty) > 32 { + arg.make_indirect(ccx); + } else { + arg.extend_integer_width_to(16); + } +} + +pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { + if !fty.ret.is_ignore() { + classify_ret_ty(ccx, &mut fty.ret); + } + + for arg in &mut fty.args { + if arg.is_ignore() { + continue; + } + classify_arg_ty(ccx, arg); + } +} diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 8ef7f04d4ee14..f189f22d925b9 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -101,6 +101,7 @@ mod cabi_arm; mod cabi_asmjs; mod cabi_mips; mod cabi_mips64; +mod cabi_msp430; mod cabi_powerpc; mod cabi_powerpc64; mod cabi_s390x; From 80ca1e1251b634b8b9831aa999f3f7435ccfdd16 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 14 Nov 2016 03:37:46 -0500 Subject: [PATCH 8/8] don't build an object file for emit=asm,llvm-ir --- src/librustc_driver/driver.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 48bf490d685b1..2dd83f7082359 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1056,7 +1056,11 @@ 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 || sess.target.target.options.no_integrated_as { + if sess.opts.cg.no_integrated_as || + (sess.target.target.options.no_integrated_as && + (outputs.outputs.contains_key(&OutputType::Object) || + outputs.outputs.contains_key(&OutputType::Exe))) + { let output_types = OutputTypes::new(&[(OutputType::Assembly, None)]); time(sess.time_passes(), "LLVM passes",