auto merge of #5432 : ILyoan/rust/arm_use_ndk_rebase, r=sanxiyn

Partial Fix for #5265

- Enabling LLVM ARM ehabi option.
- Add ARM debug information manually for ccall.s
- Compile object file using Android-NDK.

Current LLVM trunk version can generate ARM debug information for assembly files but it is incomplete for object files. Unwinding on ARM can be done with LLVM trunk(the LLVM submodule of rust has problem on generating ARM debug information). See #5368

The Android-NDK detour(0f89eab) can be removed after LLVM has complete feature of generating ARM debug information for object file.
This commit is contained in:
bors 2013-03-19 23:12:46 -07:00
commit 01e179840f
4 changed files with 73 additions and 26 deletions

View file

@ -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 fn is_object_or_assembly_or_exe(ot: output_type) -> bool {
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 fn run_passes(sess: Session, llmod: ModuleRef, output: &Path) {
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 fn run_passes(sess: Session, llmod: ModuleRef, output: &Path) {
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 fn run_passes(sess: Session, llmod: ModuleRef, output: &Path) {
}
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 fn run_passes(sess: Session, llmod: ModuleRef, output: &Path) {
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 fn run_passes(sess: Session, llmod: ModuleRef, output: &Path) {
// 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 fn run_passes(sess: Session, llmod: ModuleRef, output: &Path) {
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 fn run_passes(sess: Session, llmod: ModuleRef, output: &Path) {
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();
}
}
}

View file

@ -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 ||

View file

@ -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

View file

@ -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;