Skip to content

Commit

Permalink
auto merge of #5432 : ILyoan/rust/arm_use_ndk_rebase, r=sanxiyn
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bors committed Mar 20, 2013
2 parents f3c879f + c1cacc3 commit 01e1798
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 26 deletions.
50 changes: 41 additions & 9 deletions src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ||
Expand All @@ -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(); }
Expand All @@ -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");
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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| {
Expand All @@ -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| {
Expand Down Expand Up @@ -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)});
Expand All @@ -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();
}
}
}
Expand Down
18 changes: 16 additions & 2 deletions src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ||
Expand Down
25 changes: 10 additions & 15 deletions src/rt/arch/arm/ccall.S
Original file line number Diff line number Diff line change
Expand Up @@ -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

6 changes: 6 additions & 0 deletions src/rustllvm/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 01e1798

Please sign in to comment.