diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index aae0528e42cc9..5bbf1c35e0dd4 100644 --- a/src/liballoc_jemalloc/lib.rs +++ b/src/liballoc_jemalloc/lib.rs @@ -78,7 +78,8 @@ const MIN_ALIGN: usize = 8; target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64", - target_arch = "mips64")))] + target_arch = "mips64", + target_arch = "s390x")))] const MIN_ALIGN: usize = 16; // MALLOCX_ALIGN(a) macro diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 2c0c6d068caae..01407d1acd2ec 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -33,7 +33,8 @@ const MIN_ALIGN: usize = 8; #[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64", - target_arch = "mips64")))] + target_arch = "mips64", + target_arch = "s390x")))] const MIN_ALIGN: usize = 16; #[no_mangle] diff --git a/src/liblibc b/src/liblibc index 49d64cae0699e..3635c1a939816 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 49d64cae0699ed9d9ed84810d737a26b0b519da8 +Subproject commit 3635c1a9398160bb6540d7289b16a547be0f02b3 diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index c2e8eccbd22a4..6526936b8c3d2 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -125,11 +125,14 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 / X0, X1 #[cfg(any(target_arch = "mips", target_arch = "mipsel", target_arch = "mips64"))] -const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1 +const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1 / A0_64, A1_64 #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4 +#[cfg(any(target_arch = "s390x"))] +const UNWIND_DATA_REG: (i32, i32) = (6, 7); // R6D, R7D + // The following code is based on GCC's C and C++ personality routines. For reference, see: // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index c2b040c32f6a3..6987c7b46165e 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -13,16 +13,17 @@ use base; use build::AllocaFcx; use common::{type_is_fat_ptr, BlockAndBuilder, C_uint}; use context::CrateContext; +use cabi_aarch64; +use cabi_arm; +use cabi_asmjs; +use cabi_mips64; +use cabi_mips; +use cabi_powerpc64; +use cabi_powerpc; +use cabi_s390x; use cabi_x86; use cabi_x86_64; use cabi_x86_win64; -use cabi_arm; -use cabi_aarch64; -use cabi_powerpc; -use cabi_powerpc64; -use cabi_mips; -use cabi_mips64; -use cabi_asmjs; use machine::{llalign_of_min, llsize_of, llsize_of_real, llsize_of_store}; use type_::Type; use type_of; @@ -484,14 +485,6 @@ impl FnType { } match &ccx.sess().target.target.arch[..] { - "x86" => cabi_x86::compute_abi_info(ccx, self), - "x86_64" => if abi == Abi::SysV64 { - cabi_x86_64::compute_abi_info(ccx, self); - } else if abi == Abi::Win64 || ccx.sess().target.target.options.is_like_windows { - cabi_x86_win64::compute_abi_info(ccx, self); - } else { - cabi_x86_64::compute_abi_info(ccx, self); - }, "aarch64" => cabi_aarch64::compute_abi_info(ccx, self), "arm" => { let flavor = if ccx.sess().target.target.target_os == "ios" { @@ -501,11 +494,20 @@ impl FnType { }; cabi_arm::compute_abi_info(ccx, self, flavor); }, + "asmjs" => cabi_asmjs::compute_abi_info(ccx, self), "mips" => cabi_mips::compute_abi_info(ccx, self), "mips64" => cabi_mips64::compute_abi_info(ccx, self), "powerpc" => cabi_powerpc::compute_abi_info(ccx, self), "powerpc64" => cabi_powerpc64::compute_abi_info(ccx, self), - "asmjs" => cabi_asmjs::compute_abi_info(ccx, self), + "s390x" => cabi_s390x::compute_abi_info(ccx, self), + "x86" => cabi_x86::compute_abi_info(ccx, self), + "x86_64" => if abi == Abi::SysV64 { + cabi_x86_64::compute_abi_info(ccx, self); + } else if abi == Abi::Win64 || ccx.sess().target.target.options.is_like_windows { + cabi_x86_win64::compute_abi_info(ccx, self); + } else { + cabi_x86_64::compute_abi_info(ccx, self); + }, a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)) } diff --git a/src/librustc_trans/cabi_s390x.rs b/src/librustc_trans/cabi_s390x.rs new file mode 100644 index 0000000000000..e92ef1eaec8ec --- /dev/null +++ b/src/librustc_trans/cabi_s390x.rs @@ -0,0 +1,168 @@ +// Copyright 2016 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 libc::c_uint; +use std::cmp; +use llvm; +use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector}; +use abi::{ArgType, FnType}; +use context::CrateContext; +use type_::Type; + +fn align_up_to(off: usize, a: usize) -> usize { + return (off + a - 1) / a * a; +} + +fn align(off: usize, ty: Type) -> usize { + let a = ty_align(ty); + return align_up_to(off, a); +} + +fn ty_align(ty: Type) -> usize { + match ty.kind() { + Integer => ((ty.int_width() as usize) + 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) + } + Vector => { + let len = ty.vector_length(); + let elt = ty.element_type(); + ty_align(elt) * len + } + _ => bug!("ty_align: unhandled type") + } +} + +fn ty_size(ty: Type) -> usize { + match ty.kind() { + Integer => ((ty.int_width() as usize) + 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 + } + Vector => { + let len = ty.vector_length(); + let elt = ty.element_type(); + let eltsz = ty_size(elt); + len * eltsz + } + _ => bug!("ty_size: unhandled type") + } +} + +fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { + if is_reg_ty(ret.ty) { + ret.extend_integer_width_to(64); + } else { + ret.make_indirect(ccx); + } +} + +fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut usize) { + let orig_offset = *offset; + let size = ty_size(arg.ty) * 8; + let mut align = ty_align(arg.ty); + + align = cmp::min(cmp::max(align, 4), 8); + *offset = align_up_to(*offset, align); + *offset += align_up_to(size, align * 8) / 8; + + if !is_reg_ty(arg.ty) { + arg.cast = Some(struct_ty(ccx, arg.ty)); + arg.pad = padding_ty(ccx, align, orig_offset); + } else { + arg.extend_integer_width_to(64); + } +} + +fn is_reg_ty(ty: Type) -> bool { + return match ty.kind() { + Integer + | Pointer + | Float + | Double + | Vector => true, + _ => false + }; +} + +fn padding_ty(ccx: &CrateContext, align: usize, offset: usize) -> Option { + if ((align - 1 ) & offset) > 0 { + Some(Type::i64(ccx)) + } else { + None + } +} + +fn coerce_to_int(ccx: &CrateContext, size: usize) -> Vec { + let int_ty = Type::i64(ccx); + let mut args = Vec::new(); + + let mut n = size / 64; + while n > 0 { + args.push(int_ty); + n -= 1; + } + + let r = size % 64; + if r > 0 { + unsafe { + args.push(Type::from_ref(llvm::LLVMIntTypeInContext(ccx.llcx(), r as c_uint))); + } + } + + args +} + +fn struct_ty(ccx: &CrateContext, ty: Type) -> Type { + let size = ty_size(ty) * 8; + Type::struct_(ccx, &coerce_to_int(ccx, size), false) +} + +pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { + if !fty.ret.is_ignore() { + classify_ret_ty(ccx, &mut fty.ret); + } + + let mut offset = if fty.ret.is_indirect() { 8 } else { 0 }; + for arg in &mut fty.args { + if arg.is_ignore() { continue; } + classify_arg_ty(ccx, arg, &mut offset); + } +} diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 6ede55d5ff49a..01a73f800391e 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -97,10 +97,11 @@ mod builder; mod cabi_aarch64; mod cabi_arm; mod cabi_asmjs; -mod cabi_mips; mod cabi_mips64; -mod cabi_powerpc; +mod cabi_mips; mod cabi_powerpc64; +mod cabi_powerpc; +mod cabi_s390x; mod cabi_x86; mod cabi_x86_64; mod cabi_x86_win64; diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 9fcc3a80b98b4..161ccf1f02b04 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -942,6 +942,11 @@ mod arch { pub const ARCH: &'static str = "powerpc64"; } +#[cfg(target_arch = "s390x")] +mod arch { + pub const ARCH: &'static str = "s390x"; +} + #[cfg(target_arch = "le32")] mod arch { pub const ARCH: &'static str = "le32"; diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs index 0f62877500b2c..1c19e58818d74 100644 --- a/src/libstd/os/linux/raw.rs +++ b/src/libstd/os/linux/raw.rs @@ -160,6 +160,11 @@ mod arch { pub use libc::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t}; } +#[cfg(target_arch = "s390x")] +mod arch { + pub use libc::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t}; +} + #[cfg(target_arch = "aarch64")] mod arch { use os::raw::{c_long, c_int}; diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs index 55d8ad17460dd..6c5c1b90a4a92 100644 --- a/src/libstd/os/raw.rs +++ b/src/libstd/os/raw.rs @@ -17,14 +17,16 @@ all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc", - target_arch = "powerpc64"))))] + target_arch = "powerpc64", + target_arch = "s390x"))))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8; #[cfg(not(any(target_os = "android", target_os = "emscripten", all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc", - target_arch = "powerpc64")))))] + target_arch = "powerpc64", + target_arch = "s390x")))))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8; #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8; #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8; diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs index 8292a68417810..1ffc28668a3b3 100644 --- a/src/libunwind/libunwind.rs +++ b/src/libunwind/libunwind.rs @@ -59,6 +59,9 @@ pub const unwinder_private_data_size: usize = 2; #[cfg(target_arch = "mips64")] pub const unwinder_private_data_size: usize = 2; +#[cfg(target_arch = "s390x")] +pub const unwinder_private_data_size: usize = 2; + #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] pub const unwinder_private_data_size: usize = 2;