Support ARM and Android

Conflicts:
	src/libcore/os.rs
	src/librustc/back/link.rs
	src/librustc/driver/driver.rs
	src/librustc/metadata/loader.rs
	src/librustc/middle/trans/base.rs
This commit is contained in:
kyeongwoon 2012-11-30 09:21:49 +09:00 committed by Brian Anderson
parent 27e6a0fa56
commit 987f824f23
35 changed files with 599 additions and 30 deletions

View File

@ -241,7 +241,7 @@ DRIVER_CRATE := $(S)src/driver/driver.rs
######################################################################
# FIXME: x86-ism
LLVM_COMPONENTS=x86 ipo bitreader bitwriter linker asmparser jit mcjit \
LLVM_COMPONENTS=x86 arm ipo bitreader bitwriter linker asmparser jit mcjit \
interpreter
define DEF_LLVM_VARS

2
configure vendored
View File

@ -717,7 +717,7 @@ do
then
msg "configuring LLVM for $t"
LLVM_TARGETS="--enable-targets=x86,x86_64"
LLVM_TARGETS="--enable-targets=x86,x86_64,arm"
LLVM_BUILD="--build=$t"
LLVM_HOST="--host=$t"
LLVM_TARGET="--target=$t"

View File

@ -40,11 +40,13 @@ struct AllocHeader { priv opaque: () }
struct MemoryRegion { priv opaque: () }
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
struct Registers {
data: [u32 * 16]
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
struct Context {
regs: Registers,
next: *Context,
@ -70,6 +72,7 @@ struct BoxedRegion {
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
struct Task {
// Public fields
refcount: intptr_t, // 0

View File

@ -198,12 +198,14 @@ pub mod types {
// Standard types that are scalar but vary by OS and arch.
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
pub mod os {
pub mod common {
pub mod posix01 {}
}
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "arm")]
pub mod arch {
pub mod c95 {
pub type c_char = i8;
@ -797,6 +799,7 @@ pub mod consts {
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
pub mod os {
pub mod c95 {
pub const EXIT_FAILURE : int = 1;
@ -1264,6 +1267,7 @@ pub mod funcs {
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
pub mod posix88 {
@ -1283,7 +1287,8 @@ pub mod funcs {
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
unsafe fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
#[cfg(target_os = "android")]
unsafe fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
#[cfg(target_os = "macos")]
#[link_name = "fstat64"]
@ -1294,6 +1299,7 @@ pub mod funcs {
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "android")]
unsafe fn stat(path: *c_char, buf: *mut stat) -> c_int;
#[cfg(target_os = "macos")]
@ -1382,6 +1388,7 @@ pub mod funcs {
}
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
pub mod posix01 {
@ -1394,6 +1401,7 @@ pub mod funcs {
pub extern mod stat_ {
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "android")]
unsafe fn lstat(path: *c_char, buf: *mut stat) -> c_int;
#[cfg(target_os = "macos")]
@ -1410,6 +1418,7 @@ pub mod funcs {
unsafe fn fsync(fd: c_int) -> c_int;
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
unsafe fn fdatasync(fd: c_int) -> c_int;
unsafe fn setenv(name: *c_char, val: *c_char,
@ -1442,6 +1451,7 @@ pub mod funcs {
#[cfg(target_os = "win32")]
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
pub mod posix08 {
@ -1473,6 +1483,7 @@ pub mod funcs {
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "win32")]
pub mod bsd44 {
}
@ -1492,6 +1503,7 @@ pub mod funcs {
}
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
pub mod extra {
}

View File

@ -325,6 +325,7 @@ pub fn fsync_fd(fd: c_int, _level: io::fsync::Level) -> c_int {
}
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
pub fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
unsafe {
use libc::funcs::posix01::unistd::*;
@ -449,6 +450,7 @@ pub fn self_exe_path() -> Option<Path> {
}
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
fn load_self() -> Option<~str> {
unsafe {
use libc::funcs::posix01::unistd::readlink;
@ -876,6 +878,7 @@ pub fn real_args() -> ~[~str] {
}
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
pub fn real_args() -> ~[~str] {
unsafe {
@ -976,7 +979,6 @@ pub mod consts {
pub const FAMILY: &str = "windows";
}
#[cfg(target_os = "macos")]
use os::consts::macos::*;
@ -986,6 +988,9 @@ pub mod consts {
#[cfg(target_os = "linux")]
use os::consts::linux::*;
#[cfg(target_os = "android")]
use os::consts::android::*;
#[cfg(target_os = "win32")]
use os::consts::win32::*;
@ -1010,6 +1015,13 @@ pub mod consts {
pub const EXE_SUFFIX: &str = "";
}
pub mod android {
pub const SYSNAME: &str = "android";
pub const DLL_PREFIX: &str = "lib";
pub const DLL_SUFFIX: &str = ".so";
pub const EXE_SUFFIX: &str = "";
}
pub mod win32 {
pub const SYSNAME: &str = "win32";
pub const DLL_PREFIX: &str = "";

View File

@ -89,8 +89,10 @@ pub pure fn Path(s: &str) -> Path {
}
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
mod stat {
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "arm")]
pub mod arch {
use libc;

View File

@ -405,6 +405,7 @@ pub fn waitpid(pid: pid_t) -> int {
#[cfg(unix)]
fn waitpid_os(pid: pid_t) -> int {
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
fn WIFEXITED(status: i32) -> bool {
(status & 0xffi32) == 0i32
}
@ -416,6 +417,7 @@ pub fn waitpid(pid: pid_t) -> int {
}
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
fn WEXITSTATUS(status: i32) -> i32 {
(status >> 8i32) & 0xffi32
}

85
src/librustc/back/arm.rs Normal file
View File

@ -0,0 +1,85 @@
// Copyright 2012 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use back::target_strs;
use driver::session;
use session::sess_os_to_meta_os;
use metadata::loader::meta_section_name;
fn get_target_strs(target_os: session::os) -> target_strs::t {
return {
module_asm: ~"",
meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)),
data_layout: match target_os {
session::os_macos => {
~"e-p:32:32:32" +
~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
~"-f32:32:32-f64:64:64" +
~"-v64:64:64-v128:64:128" +
~"-a0:0:64-n32"
}
session::os_win32 => {
~"e-p:32:32:32" +
~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
~"-f32:32:32-f64:64:64" +
~"-v64:64:64-v128:64:128" +
~"-a0:0:64-n32"
}
session::os_linux => {
~"e-p:32:32:32" +
~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
~"-f32:32:32-f64:64:64" +
~"-v64:64:64-v128:64:128" +
~"-a0:0:64-n32"
}
session::os_android => {
~"e-p:32:32:32" +
~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
~"-f32:32:32-f64:64:64" +
~"-v64:64:64-v128:64:128" +
~"-a0:0:64-n32"
}
session::os_freebsd => {
~"e-p:32:32:32" +
~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
~"-f32:32:32-f64:64:64" +
~"-v64:64:64-v128:64:128" +
~"-a0:0:64-n32"
}
},
target_triple: match target_os {
session::os_macos => ~"arm-apple-darwin",
session::os_win32 => ~"arm-pc-mingw32",
session::os_linux => ~"arm-unknown-linux",
session::os_android => ~"arm-unknown-android",
session::os_freebsd => ~"arm-unknown-freebsd"
},
cc_args: ~[~"-marm"]
};
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//

View File

@ -30,7 +30,7 @@ use core::cmp;
use core::hash;
use core::io::{Writer, WriterUtil};
use core::libc::{c_int, c_uint, c_char};
use core::os::consts::{macos, freebsd, linux, win32};
use core::os::consts::{macos, freebsd, linux, android, win32};
use core::os;
use core::ptr;
use core::run;
@ -43,7 +43,7 @@ use syntax::ast_map::{path, path_mod, path_name};
use syntax::attr;
use syntax::print::pprust;
pub enum output_type {
enum output_type {
output_type_none,
output_type_bitcode,
output_type_assembly,
@ -712,6 +712,7 @@ fn output_dll_filename(os: session::os, lm: &link_meta) -> ~str {
session::os_win32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
session::os_macos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
session::os_linux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
session::os_android => (android::DLL_PREFIX, android::DLL_SUFFIX),
session::os_freebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
};
return str::from_slice(dll_prefix) + libname +
@ -758,7 +759,10 @@ fn link_binary(sess: Session,
// For win32, there is no cc command,
// so we add a condition to make it use gcc.
let cc_prog: ~str =
if sess.targ_cfg.os == session::os_win32 { ~"gcc" } else { ~"cc" };
if sess.targ_cfg.os == session::os_android {
~"arm-linux-androideabi-g++"
} else if sess.targ_cfg.os == session::os_win32 { ~"gcc" }
else { ~"cc" };
// The invocations of cc share some flags across platforms
let mut cc_args =
@ -831,6 +835,11 @@ fn link_binary(sess: Session,
// have to be explicit about linking to it. See #2510
cc_args.push(~"-lm");
}
else if sess.targ_cfg.os == session::os_android {
cc_args.push_all(~[~"-ldl", ~"-llog", ~"-lsupc++",
~"-lgnustl_shared"]);
cc_args.push(~"-lm");
}
if sess.targ_cfg.os == session::os_freebsd {
cc_args.push_all(~[~"-pthread", ~"-lrt",
@ -851,7 +860,9 @@ fn link_binary(sess: Session,
}
// Stack growth requires statically linking a __morestack function
if sess.targ_cfg.os != session::os_android {
cc_args.push(~"-lmorestack");
}
// FIXME (#2397): At some point we want to rpath our guesses as to where
// extern libraries might live, based on the addl_lib_search_paths

View File

@ -130,7 +130,8 @@ fn get_rpath_relative_to_output(os: session::os,
// Mac doesn't appear to support $ORIGIN
let prefix = match os {
session::os_linux | session::os_freebsd => "$ORIGIN",
session::os_android |session::os_linux | session::os_freebsd
=> "$ORIGIN",
session::os_macos => "@executable_path",
session::os_win32 => util::unreachable()
};
@ -331,6 +332,7 @@ mod test {
#[test]
#[cfg(target_os = "linux")]
#[cfg(target_os = "andorid")]
fn test_rpath_relative() {
let o = session::os_linux;
let res = get_rpath_relative_to_output(o,

View File

@ -35,6 +35,9 @@ fn get_target_strs(target_os: session::os) -> target_strs::t {
session::os_linux => {
~"e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32"
}
session::os_android => {
~"e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32"
}
session::os_freebsd => {
~"e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32"
@ -45,6 +48,7 @@ fn get_target_strs(target_os: session::os) -> target_strs::t {
session::os_macos => ~"i686-apple-darwin",
session::os_win32 => ~"i686-pc-mingw32",
session::os_linux => ~"i686-unknown-linux-gnu",
session::os_android => ~"i686-unknown-android-gnu",
session::os_freebsd => ~"i686-unknown-freebsd"
},

View File

@ -39,6 +39,11 @@ fn get_target_strs(target_os: session::os) -> target_strs::t {
~"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+
~"s0:64:64-f80:128:128-n8:16:32:64-S128"
}
session::os_android => {
~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+
~"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+
~"s0:64:64-f80:128:128-n8:16:32:64-S128"
}
session::os_freebsd => {
~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+
@ -51,6 +56,7 @@ fn get_target_strs(target_os: session::os) -> target_strs::t {
session::os_macos => ~"x86_64-apple-darwin",
session::os_win32 => ~"x86_64-pc-mingw32",
session::os_linux => ~"x86_64-unknown-linux-gnu",
session::os_android => ~"x86_64-unknown-android-gnu",
session::os_freebsd => ~"x86_64-unknown-freebsd",
},

View File

@ -12,7 +12,7 @@
use core::prelude::*;
use back::link;
use back::{x86, x86_64};
use back::{arm, x86, x86_64};
use front;
use lib::llvm::llvm;
use metadata::{creader, cstore, filesearch};
@ -74,9 +74,18 @@ fn default_configuration(sess: Session, +argv0: ~str, input: input) ->
session::os_win32 => ~"msvcrt.dll",
session::os_macos => ~"libc.dylib",
session::os_linux => ~"libc.so.6",
session::os_android => ~"libc.so",
session::os_freebsd => ~"libc.so.7"
// _ { "libc.so" }
};
let tos = match sess.targ_cfg.os {
session::os_win32 => ~"win32",
session::os_macos => ~"macos",
session::os_linux => ~"linux",
session::os_android => ~"android",
session::os_freebsd => ~"freebsd"
// _ { "libc.so" }
};
let mk = attr::mk_name_value_item_str;
@ -88,7 +97,7 @@ fn default_configuration(sess: Session, +argv0: ~str, input: input) ->
return ~[ // Target bindings.
attr::mk_word_item(str::from_slice(os::FAMILY)),
mk(~"target_os", str::from_slice(os::SYSNAME)),
mk(~"target_os", tos),
mk(~"target_family", str::from_slice(os::FAMILY)),
mk(~"target_arch", arch),
mk(~"target_word_size", wordsz),
@ -424,6 +433,8 @@ fn get_os(triple: ~str) -> Option<session::os> {
Some(session::os_macos)
} else if str::contains(triple, ~"linux") {
Some(session::os_linux)
} else if str::contains(triple, ~"android") {
Some(session::os_android)
} else if str::contains(triple, ~"freebsd") {
Some(session::os_freebsd)
} else { None }
@ -463,7 +474,7 @@ fn build_target_config(sopts: @session::options,
let target_strs = match arch {
session::arch_x86 => x86::get_target_strs(os),
session::arch_x86_64 => x86_64::get_target_strs(os),
session::arch_arm => x86::get_target_strs(os)
session::arch_arm => arm::get_target_strs(os)
};
let target_cfg: @session::config =
@{os: os, arch: arch, target_strs: target_strs, int_type: int_type,

View File

@ -29,7 +29,7 @@ use syntax::parse::parse_sess;
use syntax::{ast, codemap};
use syntax;
enum os { os_win32, os_macos, os_linux, os_freebsd, }
enum os { os_win32, os_macos, os_linux, os_android, os_freebsd, }
impl os : cmp::Eq {
pure fn eq(&self, other: &os) -> bool {
@ -326,6 +326,7 @@ fn sess_os_to_meta_os(os: os) -> metadata::loader::os {
match os {
os_win32 => loader::os_win32,
os_linux => loader::os_linux,
os_android => loader::os_android,
os_macos => loader::os_macos,
os_freebsd => loader::os_freebsd
}

View File

@ -28,7 +28,7 @@ use core::cast;
use core::flate;
use core::io::WriterUtil;
use core::io;
use core::os::consts::{macos, freebsd, linux, win32};
use core::os::consts::{macos, freebsd, linux, android, win32};
use core::option;
use core::ptr;
use core::str;
@ -36,7 +36,7 @@ use core::uint;
use core::vec;
export os;
export os_macos, os_win32, os_linux, os_freebsd;
export os_macos, os_win32, os_linux, os_freebsd, os_android;
export ctxt;
export load_library_crate;
export list_file_metadata;
@ -49,6 +49,7 @@ enum os {
os_macos,
os_win32,
os_linux,
os_android,
os_freebsd
}
@ -86,6 +87,7 @@ fn libname(cx: ctxt) -> {prefix: ~str, suffix: ~str} {
os_win32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
os_macos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
os_linux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
os_android => (android::DLL_PREFIX, android::DLL_SUFFIX),
os_freebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
};
return {
@ -251,6 +253,7 @@ fn meta_section_name(os: os) -> ~str {
os_macos => ~"__DATA,__note.rustc",
os_win32 => ~".note.rustc",
os_linux => ~".note.rustc",
os_android => ~".note.rustc",
os_freebsd => ~".note.rustc"
}
}

View File

@ -2152,7 +2152,9 @@ fn register_fn_fuller(ccx: @crate_ctxt,
let llfn: ValueRef = decl_fn(ccx.llmod, copy ps, cc, llfty);
ccx.item_symbols.insert(node_id, ps);
let is_main = is_main_name(path) && !ccx.sess.building_library;
let is_main = is_main_name(path) && (!ccx.sess.building_library ||
(ccx.sess.building_library &&
ccx.sess.targ_cfg.os == session::os_android));
if is_main { create_main_wrapper(ccx, sp, llfn); }
llfn
}
@ -2202,7 +2204,12 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef) {
#[cfg(unix)]
fn main_name() -> ~str { return ~"main"; }
let llfty = T_fn(~[ccx.int_type, ccx.int_type], ccx.int_type);
let llfn = decl_cdecl_fn(ccx.llmod, main_name(), llfty);
let llfn = if ccx.sess.building_library {
decl_cdecl_fn(ccx.llmod, ~"amain", llfty)
} else {
decl_cdecl_fn(ccx.llmod, main_name(), llfty)
};
let llbb = str::as_c_str(~"top", |buf| {
unsafe {
llvm::LLVMAppendBasicBlock(llfn, buf)
@ -2217,14 +2224,16 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef) {
val_ty(crate_map)], ccx.int_type);
let start = decl_cdecl_fn(ccx.llmod, ~"rust_start", start_ty);
let args = unsafe {
~[
rust_main,
llvm::LLVMGetParam(llfn, 0 as c_uint),
llvm::LLVMGetParam(llfn, 1 as c_uint),
crate_map
]
let args = if ccx.sess.building_library unsafe {
~[rust_main,
llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False),
llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False),
crate_map]
} else unsafe {
~[rust_main, llvm::LLVMGetParam(llfn, 0 as c_uint),
llvm::LLVMGetParam(llfn, 1 as c_uint), crate_map]
};
let result = unsafe {
llvm::LLVMBuildCall(bld, start, vec::raw::to_ptr(args),
args.len() as c_uint, noname())

View File

@ -15,6 +15,7 @@ use core::prelude::*;
use back::{link, abi};
use driver::session::arch_x86_64;
use driver::session::arch_arm;
use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg};
use lib::llvm::{Struct, Array, ModuleRef, CallConv, Attribute};
use lib::llvm::{StructRetAttribute, ByValAttribute};
@ -494,6 +495,8 @@ fn c_stack_tys(ccx: @crate_ctxt,
let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty);
let x86_64 = if ccx.sess.targ_cfg.arch == arch_x86_64 {
option::Some(x86_64_tys(llargtys, llretty, ret_def))
} else if ccx.sess.targ_cfg.arch == arch_arm {
option::Some(x86_64_tys(llargtys, llretty, ret_def))
} else {
option::None
};
@ -1491,6 +1494,14 @@ fn register_foreign_fn(ccx: @crate_ctxt,
register_fn_fuller(ccx, sp, /*bad*/copy path, node_id, attrs,
t, lib::llvm::CCallConv, fnty)
}
} else if ccx.sess.targ_cfg.arch == arch_arm {
let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty);
let x86_64 = x86_64_tys(llargtys, llretty, ret_def);
do decl_x86_64_fn(x86_64) |fnty| {
register_fn_fuller(ccx, sp, /*bad*/copy path, node_id, attrs,
t, lib::llvm::CCallConv, fnty)
}
} else {
let llfty = T_fn(llargtys, llretty);
register_fn_fuller(ccx, sp, path, node_id, attrs,

View File

@ -162,6 +162,8 @@ mod back {
#[legacy_exports]
mod upcall;
#[legacy_exports]
mod arm;
#[legacy_exports]
mod x86;
#[legacy_exports]
mod x86_64;

View File

@ -1291,6 +1291,7 @@ pub mod test {
#[cfg(target_os="win32")]
#[cfg(target_os="darwin")]
#[cfg(target_os="linux")]
#[cfg(target_os="android")]
pub mod tcp_ipv4_server_and_client_test {
#[cfg(target_arch="x86_64")]
pub mod impl64 {
@ -1329,6 +1330,7 @@ pub mod test {
}
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub mod impl32 {
use net::tcp::test::*;

View File

@ -109,6 +109,7 @@ pub type uv_tcp_t_32bit_unix_riders = {
a29: *u8
};
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub type uv_tcp_t_32bit_unix_riders = {
a29: *u8, a30: *u8, a31: *u8,
a32: *u8, a33: *u8, a34: *u8,
@ -165,6 +166,7 @@ pub type uv_write_t_32bit_unix_riders = {
a13: *u8
};
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub type uv_write_t_32bit_unix_riders = {
a13: *u8, a14: *u8
};
@ -192,6 +194,7 @@ pub type uv_async_t_32bit_unix_riders = {
a10: *u8
};
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub type uv_async_t_32bit_unix_riders = {
a10: *u8, a11: *u8, a12: *u8, a13: *u8
};
@ -220,6 +223,7 @@ pub type uv_timer_t_32bit_unix_riders = {
a10: *u8, a11: *u8
};
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub type uv_timer_t_32bit_unix_riders = {
a10: *u8, a11: *u8, a12: *u8, a13: *u8,
a14: *u8, a15: *u8, a16: *u8
@ -249,6 +253,7 @@ pub type sockaddr_in6 = {
a2: *u8, a3: *u8
};
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub type sockaddr_in6 = {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8,
@ -267,6 +272,7 @@ pub mod addr_in_impl {
a2: *u8, a3: *u8
};
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub type addr_in = {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8,
@ -285,6 +291,7 @@ pub mod addr_in_impl {
// unix size: 48, 32bit: 32
pub type addrinfo = addrinfo_impl::addrinfo;
#[cfg(target_os="linux")]
#[cfg(target_os="android")]
pub mod addrinfo_impl {
#[cfg(target_arch="x86_64")]
pub type addrinfo = {
@ -292,6 +299,7 @@ pub mod addrinfo_impl {
a04: *u8, a05: *u8
};
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub type addrinfo = {
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8
@ -328,6 +336,7 @@ pub mod uv_ll_struct_stubgen {
pub fn gen_stub_uv_tcp_t() -> uv_tcp_t {
return gen_stub_os();
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
pub fn gen_stub_os() -> uv_tcp_t {
@ -358,6 +367,7 @@ pub mod uv_ll_struct_stubgen {
};
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub fn gen_stub_arch() -> uv_tcp_t {
return { fields: { loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
@ -443,6 +453,7 @@ pub mod uv_ll_struct_stubgen {
};
}
#[cfg(target_arch = "x86")]
#[cfg(target_arch="arm")]
pub fn gen_stub_arch() -> uv_async_t {
return { fields: { loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
@ -492,6 +503,7 @@ pub mod uv_ll_struct_stubgen {
};
}
#[cfg(target_arch = "x86")]
#[cfg(target_arch="arm")]
pub fn gen_stub_arch() -> uv_timer_t {
return { fields: { loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
@ -541,6 +553,7 @@ pub mod uv_ll_struct_stubgen {
};
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub fn gen_stub_arch() -> uv_write_t {
return { fields: { loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
@ -1571,6 +1584,7 @@ pub mod test {
#[cfg(target_os="win32")]
#[cfg(target_os="darwin")]
#[cfg(target_os="linux")]
#[cfg(target_os="android")]
pub mod tcp_and_server_client_test {
#[cfg(target_arch="x86_64")]
pub mod impl64 {
@ -1581,6 +1595,7 @@ pub mod test {
}
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub mod impl32 {
use uv_ll::test::*;
#[test]

View File

@ -0,0 +1,47 @@
.text
.code 32
.arm
.align
.globl swap_registers
swap_registers:
str r0, [r0, #0]
str r3, [r0, #12]
str r4, [r0, #16]
str r5, [r0, #20]
str r6, [r0, #24]
str r7, [r0, #28]
str r8, [r0, #32]
str r9, [r0, #36]
str r10, [r0, #40]
str r11, [r0, #44]
str r12, [r0, #48]
str sp, [r0, #52]
str lr, [r0, #56]
mrs r2, cpsr
str r2, [r0, #64]
ldr r0, [r1, #0]
ldr r3, [r1, #12]
ldr r4, [r1, #16]
ldr r5, [r1, #20]
ldr r6, [r1, #24]
ldr r7, [r1, #28]
ldr r8, [r1, #32]
ldr r9, [r1, #36]
ldr r10, [r1, #40]
ldr r11, [r1, #44]
ldr r12, [r1, #48]
ldr sp, [r1, #52]
ldr lr, [r1, #56]
ldr r2, [r1, #64]
msr cpsr_cxsf, r2
mov pc, lr

27
src/rt/arch/arm/ccall.S Normal file
View File

@ -0,0 +1,27 @@
.text
.code 32
.arm
.align
.globl __morestack
.hidden __morestack
__morestack:
mov r3, sp
mov sp, r2
str r3, [sp]
str lr, [sp, #-4]
sub sp, #8
blx r1
add sp, #8
ldr lr, [sp, #-4]
ldr r3, [sp]
mov sp, r3
mov pc, lr

View File

@ -0,0 +1,36 @@
#include "context.h"
#include "../../rust_globals.h"
extern "C" void CDECL swap_registers(registers_t *oregs,
registers_t *regs)
asm ("swap_registers");
context::context()
{
assert((void*)&regs == (void*)this);
memset(&regs, 0, sizeof(regs));
}
void context::swap(context &out)
{
swap_registers(&out.regs, &regs);
}
void context::call(void *f, void *arg, void *stack)
{
// Get the current context, which we will then modify to call the
// given function.
swap(*this);
// set up the stack
uint32_t *sp = ( uint32_t *)stack;
//sp = align_down(sp);
// The final return address. 0 indicates the bottom of the stack
*--sp = 0;
regs.data[0] = ( uint32_t )arg; // r0
regs.data[13] = ( uint32_t )sp; //#52 sp, r13
regs.data[14] = ( uint32_t )f; //#60 pc, r15 --> lr,
// Last base pointer on the stack should be 0
}

43
src/rt/arch/arm/context.h Normal file
View File

@ -0,0 +1,43 @@
// -*- mode: c++ -*-
#ifndef CONTEXT_H
#define CONTEXT_H
#include <cstdlib>
#include <inttypes.h>
#include <stdint.h>
//#include <xmmintrin.h>
#include "vg/memcheck.h"
template<typename T>
T align_down(T sp)
{
// There is no platform we care about that needs more than a
// 16-byte alignment.
return (T)((uint32_t)sp & ~(16 - 1));
}
// The struct in which we store the saved data. This is mostly the
// volatile registers and instruction pointer, but it also includes
// RCX/RDI which are used to pass arguments. The indices for each
// register are found in "regs.h". Note that the alignment must be
// 16 bytes so that SSE instructions can be used.
#include "regs.h"
struct registers_t {
uint32_t data[RUSTRT_MAX];
} __attribute__((aligned(16)));
class context {
public:
registers_t regs;
context();
context *next;
void swap(context &out);
void call(void *f, void *arg, void *sp);
};
#endif

15
src/rt/arch/arm/gpr.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "gpr.h"
#define LOAD(rn) do { \
uintptr_t tmp; \
asm("mov %%" #rn ",%0" : "=r" (tmp) :); \
this->rn = tmp; \
} while (0)
void rust_gpr::load() {
LOAD(r0); LOAD(r1); LOAD(r2); LOAD(r3);
LOAD(r4); LOAD(r5); LOAD(r6); LOAD(r7);
LOAD(r8); LOAD(r9); LOAD(r10); LOAD(r11);
LOAD(r12); LOAD(r13); LOAD(r14); LOAD(r15);
}

23
src/rt/arch/arm/gpr.h Normal file
View File

@ -0,0 +1,23 @@
// General-purpose registers. This structure is used during stack crawling.
#ifndef GPR_H
#define GPR_H
#include "rust_gpr_base.h"
class rust_gpr : public rust_gpr_base {
public:
uintptr_t r0, r1, r2, r3, r4, r5, r6, r7;
uintptr_t r8, r9, r10, r11, r12, r13, r14, r15;
inline uintptr_t get_fp() { return r11; }
inline uintptr_t get_ip() { return r12; }
inline void set_fp(uintptr_t new_fp) { r11 = new_fp; }
inline void set_ip(uintptr_t new_ip) { r12 = new_ip; }
void load();
};
#endif

View File

@ -0,0 +1,61 @@
.text
.code 32
.arm
.align
.globl record_sp_limit
.globl get_sp_limit
.globl get_sp
record_sp_limit:
mov r3, r0
ldr r0, =my_cpu
mov r1, #0
mov r2, #0
stmfd sp!, {r3, r7}
ldr r7, =345
swi #0
ldmfd sp!, {r3, r7}
movs r0, r0
movmi r0, #0
ldr r1, =my_array
str r3, [r1, r0]
mov pc, lr
get_sp_limit:
ldr r0, =my_cpu
mov r1, #0
mov r2, #0
stmfd sp!, {r4, r7}
ldr r7, =345
swi #0
ldmfd sp!, {r4, r7}
movs r0, r0
movmi r0, #0
mov r3, r0
ldr r1, =my_array
ldr r0, [r1, r3]
mov pc, lr
get_sp:
mov r0, sp
mov pc, lr
.data
my_cpu: .long 0
.global my_array
my_array:
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.end

21
src/rt/arch/arm/regs.h Normal file
View File

@ -0,0 +1,21 @@
#define RUSTRT_RBX 0
#define RUSTRT_RSP 1
#define RUSTRT_RBP 2
// RCX on Windows, RDI elsewhere
#define RUSTRT_ARG0 3
#define RUSTRT_R12 4
#define RUSTRT_R13 5
#define RUSTRT_R14 6
#define RUSTRT_R15 7
#define RUSTRT_IP 8
#define RUSTRT_MAX 32
// ARG0 is the register in which the first argument goes.
// Naturally this depends on your operating system.
# define RUSTRT_ARG0_S r0
# define RUSTRT_ARG1_S r1
# define RUSTRT_ARG2_S r2
# define RUSTRT_ARG3_S r3

View File

@ -0,0 +1,61 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "rust_android_dummy.h"
#include <math.h>
#ifdef __ANDROID__
int backtrace(void **array, int size) { return 0; }
char **backtrace_symbols(void *const *array, int size) { return 0; }
void backtrace_symbols_fd (void *const *array, int size, int fd) {}
extern "C" float log2f(float f)
{
return logf( f ) / logf( 2 );
}
extern "C" double log2( double n )
{
return log( n ) / log( 2 );
}
extern "C" void telldir()
{
}
extern "C" void seekdir()
{
}
extern "C" void mkfifo()
{
}
extern "C" void abs()
{
}
extern "C" void labs()
{
}
extern "C" void rand()
{
}
extern "C" void srand()
{
}
extern "C" void atof()
{
}
extern "C" void tgammaf()
{
}
#endif

View File

@ -0,0 +1,5 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "execinfo.h"

View File

@ -33,6 +33,27 @@
extern char **environ;
#endif
#ifdef __ANDROID__
time_t
timegm(struct tm *tm)
{
time_t ret;
char *tz;
tz = getenv("TZ");
setenv("TZ", "", 1);
tzset();
ret = mktime(tm);
if (tz)
setenv("TZ", tz, 1);
else
unsetenv("TZ");
tzset();
return ret;
}
#endif
extern "C" CDECL rust_str*
last_os_error() {
rust_task *task = rust_get_current_task();

View File

@ -28,6 +28,7 @@ rust_sched_loop::rust_sched_loop(rust_scheduler *sched, int id, bool killed) :
id(id),
should_exit(false),
cached_c_stack(NULL),
extra_c_stack(NULL),
dead_task(NULL),
killed(killed),
pump_signal(NULL),

View File

@ -165,6 +165,9 @@
#define RED_ZONE_SIZE RZ_BSD_64
#endif
#endif
#ifdef __ANDROID__
#define RED_ZONE_SIZE RZ_MAC_32
#endif
struct rust_box;

View File

@ -91,6 +91,12 @@ void LLVMInitializeX86TargetMC();
void LLVMInitializeX86AsmPrinter();
void LLVMInitializeX86AsmParser();
void LLVMInitializeARMTargetInfo();
void LLVMInitializeARMTarget();
void LLVMInitializeARMTargetMC();
void LLVMInitializeARMAsmPrinter();
void LLVMInitializeARMAsmParser();
// Only initialize the platforms supported by Rust here,
// because using --llvm-root will have multiple platforms
// that rustllvm doesn't actually link to and it's pointless to put target info
@ -102,6 +108,12 @@ void LLVMRustInitializeTargets() {
LLVMInitializeX86TargetMC();
LLVMInitializeX86AsmPrinter();
LLVMInitializeX86AsmParser();
LLVMInitializeARMTargetInfo();
LLVMInitializeARMTarget();
LLVMInitializeARMTargetMC();
LLVMInitializeARMAsmPrinter();
LLVMInitializeARMAsmParser();
}
// Custom memory manager for MCJITting. It needs special features

View File

@ -383,19 +383,19 @@ LLVMInitializeInstCombine
LLVMInitializeScalarOpts
LLVMInitializeTarget
LLVMInitializeTransformUtils
LLVMInitializeARMAsmLexer
LLVMInitializeX86AsmLexer
LLVMInitializeX86AsmLexer
LLVMInitializeX86AsmParser
LLVMInitializeARMAsmParser
LLVMInitializeX86AsmParser
LLVMInitializeARMAsmPrinter
LLVMInitializeX86AsmPrinter
LLVMInitializeX86AsmPrinter
LLVMInitializeX86Disassembler
LLVMInitializeARMDisassembler
LLVMInitializeX86Disassembler
LLVMInitializeARMTarget
LLVMInitializeX86Target
LLVMInitializeX86Target
LLVMInitializeARMTargetMC
LLVMInitializeX86TargetMC
LLVMInitializeX86TargetMC
LLVMInitializeX86TargetInfo
LLVMInitializeARMTargetInfo
LLVMInitializeX86TargetInfo
LLVMInsertBasicBlock
LLVMInsertBasicBlockInContext