about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorkyeongwoon <kyeongwoon.lee@samsung.com>2012-11-30 09:21:49 +0900
committerBrian Anderson <banderson@mozilla.com>2013-01-13 16:43:39 -0800
commit987f824f233faee4aed39dac92a1b442d42965cc (patch)
tree2cf1b078738e9bf580b9ee43f674d95c403751fa /src
parent27e6a0fa5651dbda55773488c8b706adfa5cefc2 (diff)
downloadrust-987f824f233faee4aed39dac92a1b442d42965cc.tar.gz
rust-987f824f233faee4aed39dac92a1b442d42965cc.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/libcore/cleanup.rs3
-rw-r--r--src/libcore/libc.rs14
-rw-r--r--src/libcore/os.rs14
-rw-r--r--src/libcore/path.rs2
-rw-r--r--src/libcore/run.rs2
-rw-r--r--src/librustc/back/arm.rs85
-rw-r--r--src/librustc/back/link.rs17
-rw-r--r--src/librustc/back/rpath.rs4
-rw-r--r--src/librustc/back/x86.rs4
-rw-r--r--src/librustc/back/x86_64.rs6
-rw-r--r--src/librustc/driver/driver.rs17
-rw-r--r--src/librustc/driver/session.rs3
-rw-r--r--src/librustc/metadata/loader.rs7
-rw-r--r--src/librustc/middle/trans/base.rs27
-rw-r--r--src/librustc/middle/trans/foreign.rs11
-rw-r--r--src/librustc/rustc.rc2
-rw-r--r--src/libstd/net_tcp.rs2
-rw-r--r--src/libstd/uv_ll.rs15
-rw-r--r--src/rt/arch/arm/_context.S47
-rw-r--r--src/rt/arch/arm/ccall.S27
-rw-r--r--src/rt/arch/arm/context.cpp36
-rw-r--r--src/rt/arch/arm/context.h43
-rw-r--r--src/rt/arch/arm/gpr.cpp15
-rw-r--r--src/rt/arch/arm/gpr.h23
-rw-r--r--src/rt/arch/arm/record_sp.S61
-rw-r--r--src/rt/arch/arm/regs.h21
-rw-r--r--src/rt/rust_android_dummy.cpp61
-rw-r--r--src/rt/rust_android_dummy.h5
-rw-r--r--src/rt/rust_builtin.cpp21
-rw-r--r--src/rt/rust_sched_loop.cpp1
-rw-r--r--src/rt/rust_task.h3
-rw-r--r--src/rustllvm/RustWrapper.cpp12
-rw-r--r--src/rustllvm/rustllvm.def.in14
33 files changed, 597 insertions, 28 deletions
diff --git a/src/libcore/cleanup.rs b/src/libcore/cleanup.rs
index c8b96b9b23b..656f672479e 100644
--- a/src/libcore/cleanup.rs
+++ b/src/libcore/cleanup.rs
@@ -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
diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs
index cc9e4d1c5a9..ecd48fe16bc 100644
--- a/src/libcore/libc.rs
+++ b/src/libcore/libc.rs
@@ -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 {
     }
 
diff --git a/src/libcore/os.rs b/src/libcore/os.rs
index f602b230f45..ff3253a8223 100644
--- a/src/libcore/os.rs
+++ b/src/libcore/os.rs
@@ -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 = "";
diff --git a/src/libcore/path.rs b/src/libcore/path.rs
index cf1188b1f35..7f5f334ac1f 100644
--- a/src/libcore/path.rs
+++ b/src/libcore/path.rs
@@ -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;
 
diff --git a/src/libcore/run.rs b/src/libcore/run.rs
index 435feb16023..54bce77d308 100644
--- a/src/libcore/run.rs
+++ b/src/libcore/run.rs
@@ -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
         }
diff --git a/src/librustc/back/arm.rs b/src/librustc/back/arm.rs
new file mode 100644
index 00000000000..2c4e0af0f2d
--- /dev/null
+++ b/src/librustc/back/arm.rs
@@ -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:
+//
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 0512994f994..e49d9da3355 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -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
diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs
index 8378270bee4..005a5404b37 100644
--- a/src/librustc/back/rpath.rs
+++ b/src/librustc/back/rpath.rs
@@ -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,
diff --git a/src/librustc/back/x86.rs b/src/librustc/back/x86.rs
index 205867feb3d..7ac2bb73ebb 100644
--- a/src/librustc/back/x86.rs
+++ b/src/librustc/back/x86.rs
@@ -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"
         },
 
diff --git a/src/librustc/back/x86_64.rs b/src/librustc/back/x86_64.rs
index 929634e5bd3..aaf97587813 100644
--- a/src/librustc/back/x86_64.rs
+++ b/src/librustc/back/x86_64.rs
@@ -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",
         },
 
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 1e1e1d2b325..030856539a5 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -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,
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index ee34570203b..b2b6cb25dbb 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -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
     }
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index 535f45ae839..58c9a1b90f2 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -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"
     }
 }
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index a8b0da47e9a..165d9b60a61 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -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())
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 06383cfa228..4c373e0d217 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -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,
diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc
index 60780df5287..56a22899193 100644
--- a/src/librustc/rustc.rc
+++ b/src/librustc/rustc.rc
@@ -162,6 +162,8 @@ mod back {
     #[legacy_exports]
     mod upcall;
     #[legacy_exports]
+    mod arm;
+    #[legacy_exports]
     mod x86;
     #[legacy_exports]
     mod x86_64;
diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs
index 9e0dc0ff12e..847962c1773 100644
--- a/src/libstd/net_tcp.rs
+++ b/src/libstd/net_tcp.rs
@@ -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::*;
 
diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs
index 778daf131c4..eee3d60a66d 100644
--- a/src/libstd/uv_ll.rs
+++ b/src/libstd/uv_ll.rs
@@ -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]
diff --git a/src/rt/arch/arm/_context.S b/src/rt/arch/arm/_context.S
new file mode 100644
index 00000000000..8d370c2d64e
--- /dev/null
+++ b/src/rt/arch/arm/_context.S
@@ -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
+
+
diff --git a/src/rt/arch/arm/ccall.S b/src/rt/arch/arm/ccall.S
new file mode 100644
index 00000000000..4b89cc994a7
--- /dev/null
+++ b/src/rt/arch/arm/ccall.S
@@ -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
+	
+
diff --git a/src/rt/arch/arm/context.cpp b/src/rt/arch/arm/context.cpp
new file mode 100644
index 00000000000..dbf06a532a8
--- /dev/null
+++ b/src/rt/arch/arm/context.cpp
@@ -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
+}
diff --git a/src/rt/arch/arm/context.h b/src/rt/arch/arm/context.h
new file mode 100644
index 00000000000..6c7db766d6a
--- /dev/null
+++ b/src/rt/arch/arm/context.h
@@ -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
diff --git a/src/rt/arch/arm/gpr.cpp b/src/rt/arch/arm/gpr.cpp
new file mode 100644
index 00000000000..32a68d0732a
--- /dev/null
+++ b/src/rt/arch/arm/gpr.cpp
@@ -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);
+}
+
diff --git a/src/rt/arch/arm/gpr.h b/src/rt/arch/arm/gpr.h
new file mode 100644
index 00000000000..472c8a05e35
--- /dev/null
+++ b/src/rt/arch/arm/gpr.h
@@ -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
+
diff --git a/src/rt/arch/arm/record_sp.S b/src/rt/arch/arm/record_sp.S
new file mode 100644
index 00000000000..193104d53b1
--- /dev/null
+++ b/src/rt/arch/arm/record_sp.S
@@ -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
diff --git a/src/rt/arch/arm/regs.h b/src/rt/arch/arm/regs.h
new file mode 100644
index 00000000000..a49fcab1184
--- /dev/null
+++ b/src/rt/arch/arm/regs.h
@@ -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
+
+
diff --git a/src/rt/rust_android_dummy.cpp b/src/rt/rust_android_dummy.cpp
new file mode 100644
index 00000000000..76aa51723ef
--- /dev/null
+++ b/src/rt/rust_android_dummy.cpp
@@ -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
diff --git a/src/rt/rust_android_dummy.h b/src/rt/rust_android_dummy.h
new file mode 100644
index 00000000000..2e8b6f2c766
--- /dev/null
+++ b/src/rt/rust_android_dummy.h
@@ -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"
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index b16006e1f91..0919ccf7f0e 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -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();
diff --git a/src/rt/rust_sched_loop.cpp b/src/rt/rust_sched_loop.cpp
index e56ce6dd263..5ddfd88d4b4 100644
--- a/src/rt/rust_sched_loop.cpp
+++ b/src/rt/rust_sched_loop.cpp
@@ -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),
diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h
index 27694becdfb..20c9a48f1dd 100644
--- a/src/rt/rust_task.h
+++ b/src/rt/rust_task.h
@@ -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;
 
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index b01294062a6..3c38f3c6215 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -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
diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in
index 44636f4f36b..d3cbc490ada 100644
--- a/src/rustllvm/rustllvm.def.in
+++ b/src/rustllvm/rustllvm.def.in
@@ -383,19 +383,19 @@ LLVMInitializeInstCombine
 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