From a50ed7e548d879c90c453eff07a6ac4086c3a76d Mon Sep 17 00:00:00 2001 From: Akos Kiss Date: Tue, 16 Dec 2014 16:05:46 +0000 Subject: [PATCH] Initial version of AArch64 support. --- src/liballoc/heap.rs | 3 +- src/libcore/hash/sip.rs | 6 + src/libcoretest/mem.rs | 6 +- src/liblibc/lib.rs | 67 ++++++- .../target/aarch64_unknown_linux_gnu.rs | 26 +++ src/librustc_back/target/mod.rs | 6 +- src/librustc_llvm/lib.rs | 11 ++ src/librustc_trans/back/write.rs | 6 + src/librustc_trans/trans/asm.rs | 1 + src/librustc_trans/trans/cabi.rs | 4 +- src/librustc_trans/trans/cabi_aarch64.rs | 165 ++++++++++++++++++ src/librustc_trans/trans/mod.rs | 3 +- src/libstd/os.rs | 5 + src/libstd/rand/os.rs | 22 ++- src/libstd/rt/libunwind.rs | 3 + src/libstd/sys/common/stack.rs | 13 +- src/libstd/sys/unix/c.rs | 9 +- src/libstd/sys/unix/stack_overflow.rs | 1 + src/libstd/sys/unix/sync.rs | 6 +- src/libstd/thread_local/mod.rs | 16 +- src/libstd/thread_local/scoped.rs | 18 +- src/rt/arch/aarch64/_context.S | 106 +++++++++++ src/rt/arch/aarch64/macros.S | 11 ++ src/rt/arch/aarch64/morestack.S | 19 ++ src/rt/arch/aarch64/record_sp.S | 6 + 25 files changed, 506 insertions(+), 33 deletions(-) create mode 100644 src/librustc_back/target/aarch64_unknown_linux_gnu.rs create mode 100644 src/librustc_trans/trans/cabi_aarch64.rs create mode 100644 src/rt/arch/aarch64/_context.S create mode 100644 src/rt/arch/aarch64/macros.S create mode 100644 src/rt/arch/aarch64/morestack.S create mode 100644 src/rt/arch/aarch64/record_sp.S diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index c6b6a784f06e3..13eec9f7e7d27 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -120,7 +120,8 @@ unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) { target_arch = "mipsel"))] const MIN_ALIGN: uint = 8; #[cfg(any(target_arch = "x86", - target_arch = "x86_64"))] + target_arch = "x86_64", + target_arch = "aarch64"))] const MIN_ALIGN: uint = 16; #[cfg(external_funcs)] diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index 15f6768edce5b..8c890bef90f40 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -424,6 +424,12 @@ mod tests { } } + #[test] #[cfg(target_arch = "aarch64")] + fn test_hash_uint() { + let val = 0xdeadbeef_deadbeef_u64; + assert_eq!(hash(&(val as u64)), hash(&(val as uint))); + assert!(hash(&(val as u32)) != hash(&(val as uint))); + } #[test] #[cfg(target_arch = "arm")] fn test_hash_uint() { let val = 0xdeadbeef_deadbeef_u64; diff --git a/src/libcoretest/mem.rs b/src/libcoretest/mem.rs index 75ddfd5413b31..8e27ec9cae825 100644 --- a/src/libcoretest/mem.rs +++ b/src/libcoretest/mem.rs @@ -29,7 +29,8 @@ fn size_of_32() { } #[test] -#[cfg(target_arch = "x86_64")] +#[cfg(any(target_arch = "x86_64", + target_arch = "aarch64"))] fn size_of_64() { assert_eq!(size_of::(), 8u); assert_eq!(size_of::<*const uint>(), 8u); @@ -61,7 +62,8 @@ fn align_of_32() { } #[test] -#[cfg(target_arch = "x86_64")] +#[cfg(any(target_arch = "x86_64", + target_arch = "aarch64"))] fn align_of_64() { assert_eq!(align_of::(), 8u); assert_eq!(align_of::<*const uint>(), 8u); diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 6ab00cfe8fa6a..b847bc56a81a7 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -720,10 +720,14 @@ pub mod types { } - #[cfg(target_arch = "x86_64")] + #[cfg(any(target_arch = "x86_64", + target_arch = "aarch64"))] pub mod arch { pub mod c95 { + #[cfg(not(target_arch = "aarch64"))] pub type c_char = i8; + #[cfg(target_arch = "aarch64")] + pub type c_char = u8; pub type c_schar = i8; pub type c_uchar = u8; pub type c_short = i16; @@ -739,7 +743,10 @@ pub mod types { pub type clock_t = i64; pub type time_t = i64; pub type suseconds_t = i64; + #[cfg(not(target_arch = "aarch64"))] pub type wchar_t = i32; + #[cfg(target_arch = "aarch64")] + pub type wchar_t = u32; } pub mod c99 { pub type c_longlong = i64; @@ -760,6 +767,7 @@ pub mod types { pub type mode_t = u32; pub type ssize_t = i64; } + #[cfg(not(target_arch = "aarch64"))] pub mod posix01 { use types::os::arch::c95::{c_int, c_long, time_t}; use types::os::arch::posix88::{dev_t, gid_t, ino_t}; @@ -769,6 +777,7 @@ pub mod types { pub type nlink_t = u64; pub type blksize_t = i64; pub type blkcnt_t = i64; + #[repr(C)] #[deriving(Copy)] pub struct stat { pub st_dev: dev_t, @@ -802,6 +811,51 @@ pub mod types { pub __size: [u64, ..7] } } + #[cfg(target_arch = "aarch64")] + pub mod posix01 { + use types::os::arch::c95::{c_int, c_long, time_t}; + use types::os::arch::posix88::{dev_t, gid_t, ino_t}; + use types::os::arch::posix88::{mode_t, off_t}; + use types::os::arch::posix88::{uid_t}; + + pub type nlink_t = u32; + pub type blksize_t = i32; + pub type blkcnt_t = i64; + + #[repr(C)] + #[deriving(Copy)] pub struct stat { + pub st_dev: dev_t, + pub st_ino: ino_t, + pub st_mode: mode_t, + pub st_nlink: nlink_t, + pub st_uid: uid_t, + pub st_gid: gid_t, + pub st_rdev: dev_t, + pub __pad1: dev_t, + pub st_size: off_t, + pub st_blksize: blksize_t, + pub __pad2: c_int, + pub st_blocks: blkcnt_t, + pub st_atime: time_t, + pub st_atime_nsec: c_long, + pub st_mtime: time_t, + pub st_mtime_nsec: c_long, + pub st_ctime: time_t, + pub st_ctime_nsec: c_long, + pub __unused: [c_int, ..2], + } + + #[repr(C)] + #[deriving(Copy)] pub struct utimbuf { + pub actime: time_t, + pub modtime: time_t, + } + + #[repr(C)] + #[deriving(Copy)] pub struct pthread_attr_t { + pub __size: [u64, ..8] + } + } pub mod posix08 { } pub mod bsd44 { @@ -2432,7 +2486,8 @@ pub mod consts { } #[cfg(any(target_arch = "x86", target_arch = "x86_64", - target_arch = "arm"))] + target_arch = "arm", + target_arch = "aarch64"))] pub mod posix88 { use types::os::arch::c95::c_int; use types::common::c95::c_void; @@ -2927,7 +2982,9 @@ pub mod consts { pub const PTHREAD_STACK_MIN: size_t = 16384; #[cfg(all(target_os = "linux", - any(target_arch = "mips", target_arch = "mipsel")))] + any(target_arch = "mips", + target_arch = "mipsel", + target_arch = "aarch64")))] pub const PTHREAD_STACK_MIN: size_t = 131072; pub const CLOCK_REALTIME: c_int = 0; @@ -2936,6 +2993,7 @@ pub mod consts { pub mod posix08 { } #[cfg(any(target_arch = "arm", + target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64"))] pub mod bsd44 { @@ -3031,7 +3089,8 @@ pub mod consts { } #[cfg(any(target_arch = "x86", target_arch = "x86_64", - target_arch = "arm"))] + target_arch = "arm", + target_arch = "aarch64"))] pub mod extra { use types::os::arch::c95::c_int; diff --git a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs new file mode 100644 index 0000000000000..fbe7797cb0587 --- /dev/null +++ b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs @@ -0,0 +1,26 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + let base = super::linux_base::opts(); + Target { + data_layout: "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-\ + n32:64-S128".to_string(), + llvm_target: "aarch64-unknown-linux-gnu".to_string(), + target_endian: "little".to_string(), + target_word_size: "64".to_string(), + arch: "aarch64".to_string(), + target_os: "linux".to_string(), + options: base, + } +} diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index d12cb356e3faa..f79d357b100d7 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -60,6 +60,7 @@ mod arm_apple_ios; mod arm_linux_androideabi; mod arm_unknown_linux_gnueabi; mod arm_unknown_linux_gnueabihf; +mod aarch64_unknown_linux_gnu; mod i686_apple_darwin; mod i386_apple_ios; mod i686_pc_windows_gnu; @@ -88,8 +89,8 @@ pub struct Target { pub target_word_size: String, /// OS name to use for conditional compilation. pub target_os: String, - /// Architecture to use for ABI considerations. Valid options: "x86", "x86_64", "arm", and - /// "mips". "mips" includes "mipsel". + /// Architecture to use for ABI considerations. Valid options: "x86", "x86_64", "arm", + /// "aarch64", and "mips". "mips" includes "mipsel". pub arch: String, /// Optional settings with defaults. pub options: TargetOptions, @@ -335,6 +336,7 @@ impl Target { arm_linux_androideabi, arm_unknown_linux_gnueabi, arm_unknown_linux_gnueabihf, + aarch64_unknown_linux_gnu, x86_64_unknown_freebsd, diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 8b036b2501578..d02656838cd6c 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -1986,6 +1986,11 @@ extern { pub fn LLVMInitializeARMTargetMC(); pub fn LLVMInitializeARMAsmPrinter(); pub fn LLVMInitializeARMAsmParser(); + pub fn LLVMInitializeAArch64TargetInfo(); + pub fn LLVMInitializeAArch64Target(); + pub fn LLVMInitializeAArch64TargetMC(); + pub fn LLVMInitializeAArch64AsmPrinter(); + pub fn LLVMInitializeAArch64AsmParser(); pub fn LLVMInitializeMipsTargetInfo(); pub fn LLVMInitializeMipsTarget(); pub fn LLVMInitializeMipsTargetMC(); @@ -2255,6 +2260,12 @@ pub unsafe fn static_link_hack_this_sucks() { LLVMInitializeARMAsmPrinter(); LLVMInitializeARMAsmParser(); + LLVMInitializeAArch64TargetInfo(); + LLVMInitializeAArch64Target(); + LLVMInitializeAArch64TargetMC(); + LLVMInitializeAArch64AsmPrinter(); + LLVMInitializeAArch64AsmParser(); + LLVMInitializeMipsTargetInfo(); LLVMInitializeMipsTarget(); LLVMInitializeMipsTargetMC(); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index df7df2f08d983..9cf38f941eb10 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -1026,6 +1026,12 @@ unsafe fn configure_llvm(sess: &Session) { llvm::LLVMInitializeARMAsmPrinter(); llvm::LLVMInitializeARMAsmParser(); + llvm::LLVMInitializeAArch64TargetInfo(); + llvm::LLVMInitializeAArch64Target(); + llvm::LLVMInitializeAArch64TargetMC(); + llvm::LLVMInitializeAArch64AsmPrinter(); + llvm::LLVMInitializeAArch64AsmParser(); + llvm::LLVMInitializeMipsTargetInfo(); llvm::LLVMInitializeMipsTarget(); llvm::LLVMInitializeMipsTargetMC(); diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs index e3afe22897e39..f23ff114c579a 100644 --- a/src/librustc_trans/trans/asm.rs +++ b/src/librustc_trans/trans/asm.rs @@ -165,6 +165,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) // Basically what clang does #[cfg(any(target_arch = "arm", + target_arch = "aarch64", target_arch = "mips", target_arch = "mipsel"))] fn get_clobbers() -> String { diff --git a/src/librustc_trans/trans/cabi.rs b/src/librustc_trans/trans/cabi.rs index 7aabd998f7aae..1adbea4c55333 100644 --- a/src/librustc_trans/trans/cabi.rs +++ b/src/librustc_trans/trans/cabi.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -17,6 +17,7 @@ use trans::cabi_x86; use trans::cabi_x86_64; use trans::cabi_x86_win64; use trans::cabi_arm; +use trans::cabi_aarch64; use trans::cabi_mips; use trans::type_::Type; @@ -119,6 +120,7 @@ pub fn compute_abi_info(ccx: &CrateContext, cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def) }, "arm" => cabi_arm::compute_abi_info(ccx, atys, rty, ret_def), + "aarch64" => cabi_aarch64::compute_abi_info(ccx, atys, rty, ret_def), "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def), a => ccx.sess().fatal((format!("unrecognized arch \"{}\" in target specification", a)) .as_slice()), diff --git a/src/librustc_trans/trans/cabi_aarch64.rs b/src/librustc_trans/trans/cabi_aarch64.rs new file mode 100644 index 0000000000000..964b5d5ff6dbf --- /dev/null +++ b/src/librustc_trans/trans/cabi_aarch64.rs @@ -0,0 +1,165 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(non_upper_case_globals)] + +use llvm; +use llvm::{Integer, Pointer, Float, Double, Struct, Array}; +use llvm::{StructRetAttribute, ZExtAttribute}; +use trans::cabi::{FnType, ArgType}; +use trans::context::CrateContext; +use trans::type_::Type; + +use std::cmp; + +fn align_up_to(off: uint, a: uint) -> uint { + return (off + a - 1u) / a * a; +} + +fn align(off: uint, ty: Type) -> uint { + let a = ty_align(ty); + return align_up_to(off, a); +} + +fn ty_align(ty: Type) -> uint { + match ty.kind() { + Integer => { + unsafe { + ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8 + } + } + Pointer => 8, + Float => 4, + Double => 8, + Struct => { + if ty.is_packed() { + 1 + } else { + let str_tys = ty.field_types(); + str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t))) + } + } + Array => { + let elt = ty.element_type(); + ty_align(elt) + } + _ => panic!("ty_align: unhandled type") + } +} + +fn ty_size(ty: Type) -> uint { + match ty.kind() { + Integer => { + unsafe { + ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8 + } + } + Pointer => 8, + Float => 4, + Double => 8, + Struct => { + if ty.is_packed() { + let str_tys = ty.field_types(); + str_tys.iter().fold(0, |s, t| s + ty_size(*t)) + } else { + let str_tys = ty.field_types(); + let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t)); + align(size, ty) + } + } + Array => { + let len = ty.array_length(); + let elt = ty.element_type(); + let eltsz = ty_size(elt); + len * eltsz + } + _ => panic!("ty_size: unhandled type") + } +} + +fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType { + if is_reg_ty(ty) { + let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None }; + return ArgType::direct(ty, None, None, attr); + } + let size = ty_size(ty); + if size <= 16 { + let llty = if size <= 1 { + Type::i8(ccx) + } else if size <= 2 { + Type::i16(ccx) + } else if size <= 4 { + Type::i32(ccx) + } else if size <= 8 { + Type::i64(ccx) + } else { + Type::array(&Type::i64(ccx), ((size + 7 ) / 8 ) as u64) + }; + return ArgType::direct(ty, Some(llty), None, None); + } + ArgType::indirect(ty, Some(StructRetAttribute)) +} + +fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType { + if is_reg_ty(ty) { + let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None }; + return ArgType::direct(ty, None, None, attr); + } + let size = ty_size(ty); + if size <= 16 { + let llty = if size == 0 { + Type::array(&Type::i64(ccx), 0u64) + } else if size == 1 { + Type::i8(ccx) + } else if size == 2 { + Type::i16(ccx) + } else if size <= 4 { + Type::i32(ccx) + } else if size <= 8 { + Type::i64(ccx) + } else { + Type::array(&Type::i64(ccx), ((size + 7 ) / 8 ) as u64) + }; + return ArgType::direct(ty, Some(llty), None, None); + } + ArgType::indirect(ty, None) +} + +fn is_reg_ty(ty: Type) -> bool { + match ty.kind() { + Integer + | Pointer + | Float + | Double => true, + _ => false + } +} + +pub fn compute_abi_info(ccx: &CrateContext, + atys: &[Type], + rty: Type, + ret_def: bool) -> FnType { + let mut arg_tys = Vec::new(); + for &aty in atys.iter() { + let ty = classify_arg_ty(ccx, aty); + arg_tys.push(ty); + } + + let ret_ty = if ret_def { + classify_ret_ty(ccx, rty) + } else { + ArgType::direct(Type::void(ccx), None, None, None) + }; + + return FnType { + arg_tys: arg_tys, + ret_ty: ret_ty, + }; +} diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs index 9234dfc48bd66..8aed89507d914 100644 --- a/src/librustc_trans/trans/mod.rs +++ b/src/librustc_trans/trans/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -41,6 +41,7 @@ mod cabi_x86; mod cabi_x86_64; mod cabi_x86_win64; mod cabi_arm; +mod cabi_aarch64; mod cabi_mips; mod foreign; mod intrinsic; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index a049ea01b6d49..8840266e6530a 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -1414,6 +1414,11 @@ mod arch_consts { pub const ARCH: &'static str = "arm"; } +#[cfg(target_arch = "aarch64")] +mod arch_consts { + pub const ARCH: &'static str = "aarch64"; +} + #[cfg(target_arch = "mips")] mod arch_consts { pub const ARCH: &'static str = "mips"; diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index dbe5f9193298a..90c53b552ea6f 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -29,7 +29,10 @@ mod imp { use os::errno; #[cfg(all(target_os = "linux", - any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))] + any(target_arch = "x86_64", + target_arch = "x86", + target_arch = "arm", + target_arch = "aarch64")))] fn getrandom(buf: &mut [u8]) -> libc::c_long { extern "C" { fn syscall(number: libc::c_long, ...) -> libc::c_long; @@ -39,7 +42,7 @@ mod imp { const NR_GETRANDOM: libc::c_long = 318; #[cfg(target_arch = "x86")] const NR_GETRANDOM: libc::c_long = 355; - #[cfg(target_arch = "arm")] + #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] const NR_GETRANDOM: libc::c_long = 384; unsafe { @@ -48,7 +51,10 @@ mod imp { } #[cfg(not(all(target_os = "linux", - any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))] + any(target_arch = "x86_64", + target_arch = "x86", + target_arch = "arm", + target_arch = "aarch64"))))] fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 } fn getrandom_fill_bytes(v: &mut [u8]) { @@ -82,7 +88,10 @@ mod imp { } #[cfg(all(target_os = "linux", - any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))] + any(target_arch = "x86_64", + target_arch = "x86", + target_arch = "arm", + target_arch = "aarch64")))] fn is_getrandom_available() -> bool { use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Relaxed}; @@ -107,7 +116,10 @@ mod imp { } #[cfg(not(all(target_os = "linux", - any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))] + any(target_arch = "x86_64", + target_arch = "x86", + target_arch = "arm", + target_arch = "aarch64"))))] fn is_getrandom_available() -> bool { false } /// A random number generator that retrieves randomness straight from diff --git a/src/libstd/rt/libunwind.rs b/src/libstd/rt/libunwind.rs index 2feea7fa0a438..3bf2a6c30274c 100644 --- a/src/libstd/rt/libunwind.rs +++ b/src/libstd/rt/libunwind.rs @@ -75,6 +75,9 @@ pub const unwinder_private_data_size: uint = 20; #[cfg(all(target_arch = "arm", target_os = "ios"))] pub const unwinder_private_data_size: uint = 5; +#[cfg(target_arch = "aarch64")] +pub const unwinder_private_data_size: uint = 2; + #[cfg(any(target_arch = "mips", target_arch = "mipsel"))] pub const unwinder_private_data_size: uint = 2; diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs index 2a88e20c8fa1f..0b4c04aba88fe 100644 --- a/src/libstd/sys/common/stack.rs +++ b/src/libstd/sys/common/stack.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -226,6 +226,11 @@ pub unsafe fn record_sp_limit(limit: uint) { } } + // aarch64 - FIXME(AARCH64): missing... + #[cfg(target_arch = "aarch64")] + unsafe fn target_record_sp_limit(_: uint) { + } + // iOS segmented stack is disabled for now, see related notes #[cfg(all(target_arch = "arm", target_os = "ios"))] #[inline(always)] unsafe fn target_record_sp_limit(_: uint) { @@ -315,6 +320,12 @@ pub unsafe fn get_sp_limit() -> uint { } } + // aarch64 - FIXME(AARCH64): missing... + #[cfg(target_arch = "aarch64")] + unsafe fn target_get_sp_limit() -> uint { + 1024 + } + // iOS doesn't support segmented stacks yet. This function might // be called by runtime though so it is unsafe to mark it as // unreachable, let's return a fixed constant. diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs index e76f2a2b872db..ef7e882d7e6d0 100644 --- a/src/libstd/sys/unix/c.rs +++ b/src/libstd/sys/unix/c.rs @@ -28,7 +28,8 @@ pub const FIONBIO: libc::c_ulong = 0x8004667e; #[cfg(any(all(target_os = "linux", any(target_arch = "x86", target_arch = "x86_64", - target_arch = "arm")), + target_arch = "arm", + target_arch = "aarch64")), target_os = "android"))] pub const FIONBIO: libc::c_ulong = 0x5421; #[cfg(all(target_os = "linux", @@ -43,7 +44,8 @@ pub const FIOCLEX: libc::c_ulong = 0x20006601; #[cfg(any(all(target_os = "linux", any(target_arch = "x86", target_arch = "x86_64", - target_arch = "arm")), + target_arch = "arm", + target_arch = "aarch64")), target_os = "android"))] pub const FIOCLEX: libc::c_ulong = 0x5451; #[cfg(all(target_os = "linux", @@ -127,7 +129,8 @@ mod select { #[cfg(any(all(target_os = "linux", any(target_arch = "x86", target_arch = "x86_64", - target_arch = "arm")), + target_arch = "arm", + target_arch = "aarch64")), target_os = "android"))] mod signal { use libc; diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 340f95142419c..772353e703946 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -147,6 +147,7 @@ mod imp { #[cfg(any(all(target_os = "linux", target_arch = "x86"), // may not match all(target_os = "linux", target_arch = "x86_64"), all(target_os = "linux", target_arch = "arm"), // may not match + all(target_os = "linux", target_arch = "aarch64"), all(target_os = "linux", target_arch = "mips"), // may not match all(target_os = "linux", target_arch = "mipsel"), // may not match target_os = "android"))] // may not match diff --git a/src/libstd/sys/unix/sync.rs b/src/libstd/sys/unix/sync.rs index 007826b4b9d58..adf03124cbe38 100644 --- a/src/libstd/sys/unix/sync.rs +++ b/src/libstd/sys/unix/sync.rs @@ -125,15 +125,19 @@ mod os { target_arch = "mips", target_arch = "mipsel"))] const __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8; + #[cfg(target_arch = "aarch64")] + const __SIZEOF_PTHREAD_MUTEX_T: uint = 48 - 8; #[cfg(any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm", + target_arch = "aarch64", target_arch = "mips", target_arch = "mipsel"))] const __SIZEOF_PTHREAD_COND_T: uint = 48 - 8; - #[cfg(target_arch = "x86_64")] + #[cfg(any(target_arch = "x86_64", + target_arch = "aarch64"))] const __SIZEOF_PTHREAD_RWLOCK_T: uint = 56 - 8; #[cfg(any(target_arch = "x86", diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs index 4c33d1c418d96..d583c477064e3 100644 --- a/src/libstd/thread_local/mod.rs +++ b/src/libstd/thread_local/mod.rs @@ -170,17 +170,21 @@ macro_rules! thread_local { #[macro_export] macro_rules! __thread_local_inner { (static $name:ident: $t:ty = $init:expr) => ( - #[cfg_attr(any(target_os = "macos", target_os = "linux"), thread_local)] + #[cfg_attr(all(any(target_os = "macos", target_os = "linux"), + not(target_arch = "aarch64")), + thread_local)] static $name: ::std::thread_local::KeyInner<$t> = __thread_local_inner!($init, $t); ); (pub static $name:ident: $t:ty = $init:expr) => ( - #[cfg_attr(any(target_os = "macos", target_os = "linux"), thread_local)] + #[cfg_attr(all(any(target_os = "macos", target_os = "linux"), + not(target_arch = "aarch64")), + thread_local)] pub static $name: ::std::thread_local::KeyInner<$t> = __thread_local_inner!($init, $t); ); ($init:expr, $t:ty) => ({ - #[cfg(any(target_os = "macos", target_os = "linux"))] + #[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))] const INIT: ::std::thread_local::KeyInner<$t> = { ::std::thread_local::KeyInner { inner: ::std::cell::UnsafeCell { value: $init }, @@ -189,7 +193,7 @@ macro_rules! __thread_local_inner { } }; - #[cfg(not(any(target_os = "macos", target_os = "linux")))] + #[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))] const INIT: ::std::thread_local::KeyInner<$t> = { unsafe extern fn __destroy(ptr: *mut u8) { ::std::thread_local::destroy_value::<$t>(ptr); @@ -240,7 +244,7 @@ impl Key { } } -#[cfg(any(target_os = "macos", target_os = "linux"))] +#[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))] mod imp { use prelude::*; @@ -370,7 +374,7 @@ mod imp { } } -#[cfg(not(any(target_os = "macos", target_os = "linux")))] +#[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))] mod imp { use prelude::*; diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread_local/scoped.rs index 96f09190c2fe4..e4196ab9a2a09 100644 --- a/src/libstd/thread_local/scoped.rs +++ b/src/libstd/thread_local/scoped.rs @@ -73,13 +73,19 @@ macro_rules! scoped_thread_local { #[doc(hidden)] macro_rules! __scoped_thread_local_inner { (static $name:ident: $t:ty) => ( - #[cfg_attr(not(any(windows, target_os = "android", target_os = "ios")), + #[cfg_attr(not(any(windows, + target_os = "android", + target_os = "ios", + target_arch = "aarch64")), thread_local)] static $name: ::std::thread_local::scoped::Key<$t> = __scoped_thread_local_inner!($t); ); (pub static $name:ident: $t:ty) => ( - #[cfg_attr(not(any(windows, target_os = "android", target_os = "ios")), + #[cfg_attr(not(any(windows, + target_os = "android", + target_os = "ios", + target_arch = "aarch64")), thread_local)] pub static $name: ::std::thread_local::scoped::Key<$t> = __scoped_thread_local_inner!($t); @@ -87,14 +93,14 @@ macro_rules! __scoped_thread_local_inner { ($t:ty) => ({ use std::thread_local::scoped::Key as __Key; - #[cfg(not(any(windows, target_os = "android", target_os = "ios")))] + #[cfg(not(any(windows, target_os = "android", target_os = "ios", target_arch = "aarch64")))] const INIT: __Key<$t> = __Key { inner: ::std::thread_local::scoped::KeyInner { inner: ::std::cell::UnsafeCell { value: 0 as *mut _ }, } }; - #[cfg(any(windows, target_os = "android", target_os = "ios"))] + #[cfg(any(windows, target_os = "android", target_os = "ios", target_arch = "aarch64"))] const INIT: __Key<$t> = __Key { inner: ::std::thread_local::scoped::KeyInner { inner: ::std::thread_local::scoped::OS_INIT, @@ -194,7 +200,7 @@ impl Key { } } -#[cfg(not(any(windows, target_os = "android", target_os = "ios")))] +#[cfg(not(any(windows, target_os = "android", target_os = "ios", target_arch = "aarch64")))] mod imp { use std::cell::UnsafeCell; @@ -211,7 +217,7 @@ mod imp { } } -#[cfg(any(windows, target_os = "android", target_os = "ios"))] +#[cfg(any(windows, target_os = "android", target_os = "ios", target_arch = "aarch64"))] mod imp { use kinds::marker; use sys_common::thread_local::StaticKey as OsStaticKey; diff --git a/src/rt/arch/aarch64/_context.S b/src/rt/arch/aarch64/_context.S new file mode 100644 index 0000000000000..7908f97a805b2 --- /dev/null +++ b/src/rt/arch/aarch64/_context.S @@ -0,0 +1,106 @@ +#include "macros.S" + +// Mark stack as non-executable +#if defined(__linux__) && defined(__ELF__) + .section .note.GNU-stack, "", %progbits +#endif + +func rust_swap_registers + str x0, [x0, #0] + stp x2, x3, [x0, #16] + stp x4, x5, [x0, #32] + stp x6, x7, [x0, #48] + stp x8, x9, [x0, #64] + stp x10, x11, [x0, #80] + stp x12, x13, [x0, #96] + stp x14, x15, [x0, #112] + stp x16, x17, [x0, #128] + stp x18, x19, [x0, #144] + stp x20, x21, [x0, #160] + stp x22, x23, [x0, #176] + stp x24, x25, [x0, #192] + stp x26, x27, [x0, #208] + stp x28, x29, [x0, #224] + str x30, [x0, #240] + + mov x2, sp + str x2, [x0, #248] + + stp q0, q1, [x0, #256] + stp q2, q3, [x0, #288] + stp q4, q5, [x0, #320] + stp q6, q7, [x0, #352] + stp q8, q9, [x0, #384] + stp q10, q11, [x0, #416] + stp q12, q13, [x0, #448] + stp q14, q15, [x0, #480] + stp q16, q17, [x0, #512] + stp q18, q19, [x0, #544] + stp q20, q21, [x0, #576] + stp q22, q23, [x0, #608] + stp q24, q25, [x0, #640] + stp q26, q27, [x0, #672] + stp q28, q29, [x0, #704] + stp q30, q31, [x0, #736] + + mrs x2, fpcr + str x2, [x0, #768] + mrs x2, fpsr + str x2, [x0, #776] + mrs x2, nzcv + str x2, [x0, #784] + + ldr x0, [x1, #0] + ldp x2, x3, [x1, #16] + ldp x4, x5, [x1, #32] + ldp x6, x7, [x1, #48] + ldp x8, x9, [x1, #64] + ldp x10, x11, [x1, #80] + ldp x12, x13, [x1, #96] + ldp x14, x15, [x1, #112] + ldp x16, x17, [x1, #128] + ldp x18, x19, [x1, #144] + ldp x20, x21, [x1, #160] + ldp x22, x23, [x1, #176] + ldp x24, x25, [x1, #192] + ldp x26, x27, [x1, #208] + ldp x28, x29, [x1, #224] + ldr x30, [x1, #240] + + ldr x2, [x1, #248] + mov sp, x2 + + ldp q0, q1, [x1, #256] + ldp q2, q3, [x1, #288] + ldp q4, q5, [x1, #320] + ldp q6, q7, [x1, #352] + ldp q8, q9, [x1, #384] + ldp q10, q11, [x1, #416] + ldp q12, q13, [x1, #448] + ldp q14, q15, [x1, #480] + ldp q16, q17, [x1, #512] + ldp q18, q19, [x1, #544] + ldp q20, q21, [x1, #576] + ldp q22, q23, [x1, #608] + ldp q24, q25, [x1, #640] + ldp q26, q27, [x1, #672] + ldp q28, q29, [x1, #704] + ldp q30, q31, [x1, #736] + + ldr x2, [x1, #768] + msr fpcr, x2 + ldr x2, [x1, #776] + msr fpsr, x2 + ldr x2, [x1, #784] + msr nzcv, x2 + + ret +endfunc rust_swap_registers + +// For reasons of this existence, see the comments in x86_64/_context.S +func rust_bootstrap_green_task + mov x0, x0 + mov x1, x3 + mov x2, x4 + br x5 +endfunc rust_bootstrap_green_task diff --git a/src/rt/arch/aarch64/macros.S b/src/rt/arch/aarch64/macros.S new file mode 100644 index 0000000000000..ae42a5d22433c --- /dev/null +++ b/src/rt/arch/aarch64/macros.S @@ -0,0 +1,11 @@ +.macro func _name + .text + .align 2 + .globl \_name + .type \_name, %function +\_name: +.endm + +.macro endfunc _name + .size \_name, .-\_name +.endm diff --git a/src/rt/arch/aarch64/morestack.S b/src/rt/arch/aarch64/morestack.S new file mode 100644 index 0000000000000..12827cea0feda --- /dev/null +++ b/src/rt/arch/aarch64/morestack.S @@ -0,0 +1,19 @@ +#include "macros.S" + +// Mark stack as non-executable +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack, "", %progbits +#endif + +/* See i386/morestack.S for the lengthy, general explanation. */ + +.global rust_stack_exhausted + +// FIXME(AARCH64): this might not be perfectly right but works for now +func __morestack + .cfi_startproc + bl rust_stack_exhausted + // the above function ensures that it never returns + .cfi_endproc +endfunc __morestack + .hidden __morestack diff --git a/src/rt/arch/aarch64/record_sp.S b/src/rt/arch/aarch64/record_sp.S new file mode 100644 index 0000000000000..115e286866e6e --- /dev/null +++ b/src/rt/arch/aarch64/record_sp.S @@ -0,0 +1,6 @@ +#include "macros.S" + +// Mark stack as non-executable +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack, "", %progbits +#endif