######################################################################
# 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
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"
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,
}
#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
struct Task {
// Public fields
refcount: intptr_t, // 0
// 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;
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
pub mod os {
pub mod c95 {
pub const EXIT_FAILURE : int = 1;
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
pub mod posix88 {
#[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"]
#[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")]
}
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
pub mod posix01 {
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")]
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,
#[cfg(target_os = "win32")]
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
pub mod posix08 {
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
#[cfg(target_os = "win32")]
pub mod bsd44 {
}
}
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
pub mod extra {
}
}
#[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::*;
}
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
fn load_self() -> Option<~str> {
unsafe {
use libc::funcs::posix01::unistd::readlink;
}
#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
pub fn real_args() -> ~[~str] {
unsafe {
pub const FAMILY: &str = "windows";
}
-
#[cfg(target_os = "macos")]
use os::consts::macos::*;
#[cfg(target_os = "linux")]
use os::consts::linux::*;
+ #[cfg(target_os = "android")]
+ use os::consts::android::*;
+
#[cfg(target_os = "win32")]
use os::consts::win32::*;
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 = "";
}
#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
mod stat {
#[cfg(target_arch = "x86")]
+ #[cfg(target_arch = "arm")]
pub mod arch {
use libc;
#[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
}
}
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
fn WEXITSTATUS(status: i32) -> i32 {
(status >> 8i32) & 0xffi32
}
--- /dev/null
+// 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:
+//
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;
use syntax::attr;
use syntax::print::pprust;
-pub enum output_type {
+enum output_type {
output_type_none,
output_type_bitcode,
output_type_assembly,
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 +
// 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 =
// 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",
}
// 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
// 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()
};
#[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,
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"
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"
},
~"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-"+
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",
},
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};
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;
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),
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 }
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,
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 {
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
}
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;
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;
os_macos,
os_win32,
os_linux,
+ os_android,
os_freebsd
}
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 {
os_macos => ~"__DATA,__note.rustc",
os_win32 => ~".note.rustc",
os_linux => ~".note.rustc",
+ os_android => ~".note.rustc",
os_freebsd => ~".note.rustc"
}
}
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
}
#[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)
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())
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};
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
};
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,
#[legacy_exports]
mod upcall;
#[legacy_exports]
+ mod arm;
+ #[legacy_exports]
mod x86;
#[legacy_exports]
mod x86_64;
#[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 {
}
}
#[cfg(target_arch="x86")]
+ #[cfg(target_arch="arm")]
pub mod impl32 {
use net::tcp::test::*;
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,
a13: *u8
};
#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
pub type uv_write_t_32bit_unix_riders = {
a13: *u8, a14: *u8
};
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
};
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
a2: *u8, a3: *u8
};
#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
pub type sockaddr_in6 = {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8,
a2: *u8, a3: *u8
};
#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
pub type addr_in = {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8,
// 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 = {
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
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 {
};
}
#[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(),
};
}
#[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(),
};
}
#[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(),
};
}
#[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(),
#[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 {
}
}
#[cfg(target_arch="x86")]
+ #[cfg(target_arch="arm")]
pub mod impl32 {
use uv_ll::test::*;
#[test]
--- /dev/null
+.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
+
+
--- /dev/null
+.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
+
+
--- /dev/null
+
+#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*)®s == (void*)this);
+ memset(®s, 0, sizeof(regs));
+}
+
+void context::swap(context &out)
+{
+ swap_registers(&out.regs, ®s);
+}
+
+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
+}
--- /dev/null
+// -*- 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
--- /dev/null
+#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);
+}
+
--- /dev/null
+// 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
+
--- /dev/null
+.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
--- /dev/null
+#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
+
+
--- /dev/null
+// 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
--- /dev/null
+// 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"
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();
id(id),
should_exit(false),
cached_c_stack(NULL),
+ extra_c_stack(NULL),
dead_task(NULL),
killed(killed),
pump_signal(NULL),
#define RED_ZONE_SIZE RZ_BSD_64
#endif
#endif
+#ifdef __ANDROID__
+#define RED_ZONE_SIZE RZ_MAC_32
+#endif
struct rust_box;
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
LLVMInitializeX86TargetMC();
LLVMInitializeX86AsmPrinter();
LLVMInitializeX86AsmParser();
+
+ LLVMInitializeARMTargetInfo();
+ LLVMInitializeARMTarget();
+ LLVMInitializeARMTargetMC();
+ LLVMInitializeARMAsmPrinter();
+ LLVMInitializeARMAsmParser();
}
// Custom memory manager for MCJITting. It needs special features
LLVMInitializeScalarOpts
LLVMInitializeTarget
LLVMInitializeTransformUtils
+LLVMInitializeARMAsmLexer
LLVMInitializeX86AsmLexer
-LLVMInitializeX86AsmLexer
-LLVMInitializeX86AsmParser
+LLVMInitializeARMAsmParser
LLVMInitializeX86AsmParser
+LLVMInitializeARMAsmPrinter
LLVMInitializeX86AsmPrinter
-LLVMInitializeX86AsmPrinter
-LLVMInitializeX86Disassembler
+LLVMInitializeARMDisassembler
LLVMInitializeX86Disassembler
+LLVMInitializeARMTarget
LLVMInitializeX86Target
-LLVMInitializeX86Target
-LLVMInitializeX86TargetMC
+LLVMInitializeARMTargetMC
LLVMInitializeX86TargetMC
-LLVMInitializeX86TargetInfo
+LLVMInitializeARMTargetInfo
LLVMInitializeX86TargetInfo
LLVMInsertBasicBlock
LLVMInsertBasicBlockInContext