diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 84836568029be..e7a971a98a16d 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -167,15 +167,18 @@ pub mod write { use back::link::{output_type_assembly, output_type_bitcode}; use back::link::{output_type_exe, output_type_llvm_assembly}; use back::link::{output_type_object}; + use back::link::output_type; use driver::session::Session; use driver::session; use lib::llvm::llvm; use lib::llvm::{False, True, ModuleRef, mk_pass_manager, mk_target_data}; use lib; + use core::prelude::*; use core::libc::{c_char, c_int, c_uint}; use core::path::Path; use core::str; + use core::run; pub fn is_object_or_assembly_or_exe(ot: output_type) -> bool { if ot == output_type_assembly || ot == output_type_object || @@ -185,7 +188,8 @@ pub mod write { return false; } - pub fn run_passes(sess: Session, llmod: ModuleRef, output: &Path) { + pub fn run_passes(sess: Session, llmod: ModuleRef, + output_type: output_type, output: &Path) { unsafe { let opts = sess.opts; if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); } @@ -201,7 +205,7 @@ pub mod write { if opts.save_temps { - match opts.output_type { + match output_type { output_type_bitcode => { if opts.optimize != session::No { let filename = output.with_filetype("no-opt.bc"); @@ -262,7 +266,7 @@ pub mod write { llvm::LLVMPassManagerBuilderDispose(MPMB); } if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); } - if is_object_or_assembly_or_exe(opts.output_type) || opts.jit { + if is_object_or_assembly_or_exe(output_type) || opts.jit { let LLVMOptNone = 0 as c_int; // -O0 let LLVMOptLess = 1 as c_int; // -O1 let LLVMOptDefault = 2 as c_int; // -O2, -Os @@ -290,8 +294,8 @@ pub mod write { } let mut FileType; - if opts.output_type == output_type_object || - opts.output_type == output_type_exe { + if output_type == output_type_object || + output_type == output_type_exe { FileType = lib::llvm::ObjectFile; } else { FileType = lib::llvm::AssemblyFile; } // Write optimized bitcode if --save-temps was on. @@ -307,7 +311,7 @@ pub mod write { pm = mk_pass_manager(); // Save the assembly file if -S is used - if opts.output_type == output_type_assembly { + if output_type == output_type_assembly { let _: () = str::as_c_str( sess.targ_cfg.target_strs.target_triple, |buf_t| { @@ -328,8 +332,8 @@ pub mod write { // Save the object file for -c or --save-temps alone // This .o is needed when an exe is built - if opts.output_type == output_type_object || - opts.output_type == output_type_exe { + if output_type == output_type_object || + output_type == output_type_exe { let _: () = str::as_c_str( sess.targ_cfg.target_strs.target_triple, |buf_t| { @@ -375,7 +379,7 @@ pub mod write { return; } - if opts.output_type == output_type_llvm_assembly { + if output_type == output_type_llvm_assembly { // Given options "-S --emit-llvm": output LLVM assembly str::as_c_str(output.to_str(), |buf_o| { llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o)}); @@ -391,6 +395,34 @@ pub mod write { if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); } } } + + pub fn run_ndk(sess: Session, assembly: &Path, object: &Path) { + let cc_prog: ~str = match &sess.opts.android_cross_path { + &Some(copy path) => { + fmt!("%s/bin/arm-linux-androideabi-gcc", path) + } + &None => { + sess.fatal(~"need Android NDK path for building \ + (--android-cross-path)") + } + }; + let mut cc_args = ~[]; + cc_args.push(~"-c"); + cc_args.push(~"-o"); + cc_args.push(object.to_str()); + cc_args.push(assembly.to_str()); + + let prog = run::program_output(cc_prog, cc_args); + + if prog.status != 0 { + sess.err(fmt!("building with `%s` failed with code %d", + cc_prog, prog.status)); + sess.note(fmt!("%s arguments: %s", + cc_prog, str::connect(cc_args, ~" "))); + sess.note(prog.err + prog.out); + sess.abort_if_errors(); + } + } } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index dff8ec866d639..42db21282a015 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -323,9 +323,23 @@ pub fn compile_rest(sess: Session, cfg: ast::crate_cfg, }; - time(time_passes, ~"LLVM passes", || - link::write::run_passes(sess, llmod, + // NOTE: Android hack + if sess.targ_cfg.arch == session::arch_arm && + (sess.opts.output_type == link::output_type_object || + sess.opts.output_type == link::output_type_exe) { + let output_type = link::output_type_assembly; + let obj_filename = outputs.obj_filename.with_filetype("s"); + + time(time_passes, ~"LLVM passes", || + link::write::run_passes(sess, llmod, output_type, + &obj_filename)); + + link::write::run_ndk(sess, &obj_filename, &outputs.obj_filename); + } else { + time(time_passes, ~"LLVM passes", || + link::write::run_passes(sess, llmod, sess.opts.output_type, &outputs.obj_filename)); + } let stop_after_codegen = sess.opts.output_type != link::output_type_exe || diff --git a/src/rt/arch/arm/ccall.S b/src/rt/arch/arm/ccall.S index 4b89cc994a7a5..345e6462d07b0 100644 --- a/src/rt/arch/arm/ccall.S +++ b/src/rt/arch/arm/ccall.S @@ -5,23 +5,18 @@ .globl __morestack .hidden __morestack +.type __morestack, %function __morestack: - mov r3, sp + .fnstart + .save {r4, fp, lr} + push {r4, fp, lr} + .movsp r4 + mov r4, sp mov sp, r2 - - str r3, [sp] - str lr, [sp, #-4] - - sub sp, #8 - + mov fp, sp blx r1 - - add sp, #8 - - ldr lr, [sp, #-4] - ldr r3, [sp] - - mov sp, r3 + mov sp, r4 + pop {r4, fp, lr} mov pc, lr - + .fnend diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 1b3c1f6e581ec..c4846c1a62bc3 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -27,6 +27,7 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/Assembly/Parser.h" #include "llvm/Assembly/PrintModulePass.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" @@ -428,6 +429,11 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, LLVMRustInitializeTargets(); + int argc = 3; + const char* argv[] = {"rustc", "-arm-enable-ehabi", + "-arm-enable-ehabi-descriptors"}; + cl::ParseCommandLineOptions(argc, argv); + TargetOptions Options; Options.NoFramePointerElim = true; Options.EnableSegmentedStacks = EnableSegmentedStacks;