Skip to content

Commit 01e1798

Browse files
committed
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.
2 parents f3c879f + c1cacc3 commit 01e1798

File tree

4 files changed

+73
-26
lines changed

4 files changed

+73
-26
lines changed

src/librustc/back/link.rs

+41-9
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,18 @@ pub mod write {
167167
use back::link::{output_type_assembly, output_type_bitcode};
168168
use back::link::{output_type_exe, output_type_llvm_assembly};
169169
use back::link::{output_type_object};
170+
use back::link::output_type;
170171
use driver::session::Session;
171172
use driver::session;
172173
use lib::llvm::llvm;
173174
use lib::llvm::{False, True, ModuleRef, mk_pass_manager, mk_target_data};
174175
use lib;
175176

177+
use core::prelude::*;
176178
use core::libc::{c_char, c_int, c_uint};
177179
use core::path::Path;
178180
use core::str;
181+
use core::run;
179182

180183
pub fn is_object_or_assembly_or_exe(ot: output_type) -> bool {
181184
if ot == output_type_assembly || ot == output_type_object ||
@@ -185,7 +188,8 @@ pub mod write {
185188
return false;
186189
}
187190

188-
pub fn run_passes(sess: Session, llmod: ModuleRef, output: &Path) {
191+
pub fn run_passes(sess: Session, llmod: ModuleRef,
192+
output_type: output_type, output: &Path) {
189193
unsafe {
190194
let opts = sess.opts;
191195
if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); }
@@ -201,7 +205,7 @@ pub mod write {
201205

202206

203207
if opts.save_temps {
204-
match opts.output_type {
208+
match output_type {
205209
output_type_bitcode => {
206210
if opts.optimize != session::No {
207211
let filename = output.with_filetype("no-opt.bc");
@@ -262,7 +266,7 @@ pub mod write {
262266
llvm::LLVMPassManagerBuilderDispose(MPMB);
263267
}
264268
if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); }
265-
if is_object_or_assembly_or_exe(opts.output_type) || opts.jit {
269+
if is_object_or_assembly_or_exe(output_type) || opts.jit {
266270
let LLVMOptNone = 0 as c_int; // -O0
267271
let LLVMOptLess = 1 as c_int; // -O1
268272
let LLVMOptDefault = 2 as c_int; // -O2, -Os
@@ -290,8 +294,8 @@ pub mod write {
290294
}
291295

292296
let mut FileType;
293-
if opts.output_type == output_type_object ||
294-
opts.output_type == output_type_exe {
297+
if output_type == output_type_object ||
298+
output_type == output_type_exe {
295299
FileType = lib::llvm::ObjectFile;
296300
} else { FileType = lib::llvm::AssemblyFile; }
297301
// Write optimized bitcode if --save-temps was on.
@@ -307,7 +311,7 @@ pub mod write {
307311
pm = mk_pass_manager();
308312
// Save the assembly file if -S is used
309313

310-
if opts.output_type == output_type_assembly {
314+
if output_type == output_type_assembly {
311315
let _: () = str::as_c_str(
312316
sess.targ_cfg.target_strs.target_triple,
313317
|buf_t| {
@@ -328,8 +332,8 @@ pub mod write {
328332

329333
// Save the object file for -c or --save-temps alone
330334
// This .o is needed when an exe is built
331-
if opts.output_type == output_type_object ||
332-
opts.output_type == output_type_exe {
335+
if output_type == output_type_object ||
336+
output_type == output_type_exe {
333337
let _: () = str::as_c_str(
334338
sess.targ_cfg.target_strs.target_triple,
335339
|buf_t| {
@@ -375,7 +379,7 @@ pub mod write {
375379
return;
376380
}
377381

378-
if opts.output_type == output_type_llvm_assembly {
382+
if output_type == output_type_llvm_assembly {
379383
// Given options "-S --emit-llvm": output LLVM assembly
380384
str::as_c_str(output.to_str(), |buf_o| {
381385
llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o)});
@@ -391,6 +395,34 @@ pub mod write {
391395
if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
392396
}
393397
}
398+
399+
pub fn run_ndk(sess: Session, assembly: &Path, object: &Path) {
400+
let cc_prog: ~str = match &sess.opts.android_cross_path {
401+
&Some(copy path) => {
402+
fmt!("%s/bin/arm-linux-androideabi-gcc", path)
403+
}
404+
&None => {
405+
sess.fatal(~"need Android NDK path for building \
406+
(--android-cross-path)")
407+
}
408+
};
409+
let mut cc_args = ~[];
410+
cc_args.push(~"-c");
411+
cc_args.push(~"-o");
412+
cc_args.push(object.to_str());
413+
cc_args.push(assembly.to_str());
414+
415+
let prog = run::program_output(cc_prog, cc_args);
416+
417+
if prog.status != 0 {
418+
sess.err(fmt!("building with `%s` failed with code %d",
419+
cc_prog, prog.status));
420+
sess.note(fmt!("%s arguments: %s",
421+
cc_prog, str::connect(cc_args, ~" ")));
422+
sess.note(prog.err + prog.out);
423+
sess.abort_if_errors();
424+
}
425+
}
394426
}
395427
396428

src/librustc/driver/driver.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,23 @@ pub fn compile_rest(sess: Session, cfg: ast::crate_cfg,
323323

324324
};
325325

326-
time(time_passes, ~"LLVM passes", ||
327-
link::write::run_passes(sess, llmod,
326+
// NOTE: Android hack
327+
if sess.targ_cfg.arch == session::arch_arm &&
328+
(sess.opts.output_type == link::output_type_object ||
329+
sess.opts.output_type == link::output_type_exe) {
330+
let output_type = link::output_type_assembly;
331+
let obj_filename = outputs.obj_filename.with_filetype("s");
332+
333+
time(time_passes, ~"LLVM passes", ||
334+
link::write::run_passes(sess, llmod, output_type,
335+
&obj_filename));
336+
337+
link::write::run_ndk(sess, &obj_filename, &outputs.obj_filename);
338+
} else {
339+
time(time_passes, ~"LLVM passes", ||
340+
link::write::run_passes(sess, llmod, sess.opts.output_type,
328341
&outputs.obj_filename));
342+
}
329343

330344
let stop_after_codegen =
331345
sess.opts.output_type != link::output_type_exe ||

src/rt/arch/arm/ccall.S

+10-15
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,18 @@
55

66
.globl __morestack
77
.hidden __morestack
8+
.type __morestack, %function
89
__morestack:
9-
mov r3, sp
10+
.fnstart
11+
.save {r4, fp, lr}
12+
push {r4, fp, lr}
13+
.movsp r4
14+
mov r4, sp
1015
mov sp, r2
11-
12-
str r3, [sp]
13-
str lr, [sp, #-4]
14-
15-
sub sp, #8
16-
16+
mov fp, sp
1717
blx r1
18-
19-
add sp, #8
20-
21-
ldr lr, [sp, #-4]
22-
ldr r3, [sp]
23-
24-
mov sp, r3
18+
mov sp, r4
19+
pop {r4, fp, lr}
2520
mov pc, lr
26-
21+
.fnend
2722

src/rustllvm/RustWrapper.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "llvm/ADT/DenseSet.h"
2828
#include "llvm/Assembly/Parser.h"
2929
#include "llvm/Assembly/PrintModulePass.h"
30+
#include "llvm/Support/CommandLine.h"
3031
#include "llvm/Support/FormattedStream.h"
3132
#include "llvm/Support/Timer.h"
3233
#include "llvm/Support/raw_ostream.h"
@@ -428,6 +429,11 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR,
428429

429430
LLVMRustInitializeTargets();
430431

432+
int argc = 3;
433+
const char* argv[] = {"rustc", "-arm-enable-ehabi",
434+
"-arm-enable-ehabi-descriptors"};
435+
cl::ParseCommandLineOptions(argc, argv);
436+
431437
TargetOptions Options;
432438
Options.NoFramePointerElim = true;
433439
Options.EnableSegmentedStacks = EnableSegmentedStacks;

0 commit comments

Comments
 (0)