Skip to content

Commit 4812cf3

Browse files
authored
Auto merge of #36369 - uweigand:s390x, r=alexcrichton
Add s390x support This adds support for building the Rust compiler and standard library for s390x-linux, allowing a full cross-bootstrap sequence to complete. This includes: - Makefile/configure changes to allow native s390x builds - Full Rust compiler support for the s390x C ABI (only the non-vector ABI is supported at this point) - Port of the standard library to s390x - Update the liblibc submodule to a version including s390x support - Testsuite fixes to allow clean "make check" on s390x Caveats: - Resets base cpu to "z10" to bring support in sync with the default behaviour of other compilers on the platforms. (Usually, upstream supports all older processors; a distribution build may then chose to require a more recent base version.) (Also, using zEC12 causes failures in the valgrind tests since valgrind doesn't fully support this CPU yet.) - z13 vector ABI is not yet supported. To ensure compatible code generation, the -vector feature is passed to LLVM. Note that this means that even when compiling for z13, no vector instructions will be used. In the future, support for the vector ABI should be added (this will require common code support for different ABIs that need different data_layout strings on the same platform). - Two test cases are (temporarily) ignored on s390x to allow passing the test suite. The underlying issues still need to be fixed: * debuginfo/simd.rs fails because of incorrect debug information. This seems to be a LLVM bug (also seen with C code). * run-pass/union/union-basic.rs simply seems to be incorrect for all big-endian platforms. Signed-off-by: Ulrich Weigand <[email protected]>
2 parents 1fca1ab + 19b8408 commit 4812cf3

File tree

26 files changed

+253
-14
lines changed

26 files changed

+253
-14
lines changed

configure

+4
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,10 @@ case $CFG_CPUTYPE in
524524
CFG_CPUTYPE=powerpc64le
525525
;;
526526

527+
s390x)
528+
CFG_CPUTYPE=s390x
529+
;;
530+
527531
x86_64 | x86-64 | x64 | amd64)
528532
CFG_CPUTYPE=x86_64
529533
;;

mk/cfg/s390x-unknown-linux-gnu.mk

+24-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,24 @@
1-
# rustbuild-only target
1+
# s390x-unknown-linux-gnu configuration
2+
CROSS_PREFIX_s390x-unknown-linux-gnu=s390x-linux-gnu-
3+
CC_s390x-unknown-linux-gnu=$(CC)
4+
CXX_s390x-unknown-linux-gnu=$(CXX)
5+
CPP_s390x-unknown-linux-gnu=$(CPP)
6+
AR_s390x-unknown-linux-gnu=$(AR)
7+
CFG_LIB_NAME_s390x-unknown-linux-gnu=lib$(1).so
8+
CFG_STATIC_LIB_NAME_s390x-unknown-linux-gnu=lib$(1).a
9+
CFG_LIB_GLOB_s390x-unknown-linux-gnu=lib$(1)-*.so
10+
CFG_LIB_DSYM_GLOB_s390x-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
11+
CFG_CFLAGS_s390x-unknown-linux-gnu := -m64 $(CFLAGS)
12+
CFG_GCCISH_CFLAGS_s390x-unknown-linux-gnu := -g -fPIC -m64 $(CFLAGS)
13+
CFG_GCCISH_CXXFLAGS_s390x-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
14+
CFG_GCCISH_LINK_FLAGS_s390x-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m64
15+
CFG_GCCISH_DEF_FLAG_s390x-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
16+
CFG_LLC_FLAGS_s390x-unknown-linux-gnu :=
17+
CFG_INSTALL_NAME_s390x-unknown-linux-gnu =
18+
CFG_EXE_SUFFIX_s390x-unknown-linux-gnu =
19+
CFG_WINDOWSY_s390x-unknown-linux-gnu :=
20+
CFG_UNIXY_s390x-unknown-linux-gnu := 1
21+
CFG_LDPATH_s390x-unknown-linux-gnu :=
22+
CFG_RUN_s390x-unknown-linux-gnu=$(2)
23+
CFG_RUN_TARG_s390x-unknown-linux-gnu=$(call CFG_RUN_s390x-unknown-linux-gnu,,$(2))
24+
CFG_GNU_TRIPLE_s390x-unknown-linux-gnu := s390x-unknown-linux-gnu

src/liballoc_jemalloc/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ const MIN_ALIGN: usize = 8;
7878
target_arch = "x86_64",
7979
target_arch = "aarch64",
8080
target_arch = "powerpc64",
81-
target_arch = "mips64")))]
81+
target_arch = "mips64",
82+
target_arch = "s390x")))]
8283
const MIN_ALIGN: usize = 16;
8384

8485
// MALLOCX_ALIGN(a) macro

src/liballoc_system/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
const MIN_ALIGN: usize = 8;
3434
#[cfg(all(any(target_arch = "x86_64",
3535
target_arch = "aarch64",
36-
target_arch = "mips64")))]
36+
target_arch = "mips64",
37+
target_arch = "s390x")))]
3738
const MIN_ALIGN: usize = 16;
3839

3940
#[no_mangle]

src/libpanic_unwind/gcc.rs

+3
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1
130130
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
131131
const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4
132132

133+
#[cfg(target_arch = "s390x")]
134+
const UNWIND_DATA_REG: (i32, i32) = (6, 7); // R6, R7
135+
133136
// The following code is based on GCC's C and C++ personality routines. For reference, see:
134137
// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
135138
// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c

src/librustc_back/target/s390x_unknown_linux_gnu.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@ use target::{Target, TargetResult};
1212

1313
pub fn target() -> TargetResult {
1414
let mut base = super::linux_base::opts();
15-
// NOTE(zEC12) matches C toolchain
16-
base.cpu = "zEC12".to_string();
15+
// z10 is the oldest CPU supported by LLVM
16+
base.cpu = "z10".to_string();
17+
// FIXME: The data_layout string below and the ABI implementation in
18+
// cabi_s390x.rs are for now hard-coded to assume the no-vector ABI.
19+
// Pass the -vector feature string to LLVM to respect this assumption.
20+
base.features = "-vector".to_string();
1721
base.max_atomic_width = 64;
1822

1923
Ok(Target {

src/librustc_trans/abi.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use cabi_arm;
2020
use cabi_aarch64;
2121
use cabi_powerpc;
2222
use cabi_powerpc64;
23+
use cabi_s390x;
2324
use cabi_mips;
2425
use cabi_mips64;
2526
use cabi_asmjs;
@@ -301,6 +302,9 @@ impl FnType {
301302
let win_x64_gnu = target.target_os == "windows"
302303
&& target.arch == "x86_64"
303304
&& target.target_env == "gnu";
305+
let linux_s390x = target.target_os == "linux"
306+
&& target.arch == "s390x"
307+
&& target.target_env == "gnu";
304308
let rust_abi = match abi {
305309
RustIntrinsic | PlatformIntrinsic | Rust | RustCall => true,
306310
_ => false
@@ -326,7 +330,9 @@ impl FnType {
326330
if llsize_of_real(ccx, arg.ty) == 0 {
327331
// For some forsaken reason, x86_64-pc-windows-gnu
328332
// doesn't ignore zero-sized struct arguments.
329-
if is_return || rust_abi || !win_x64_gnu {
333+
// The same is true for s390x-unknown-linux-gnu.
334+
if is_return || rust_abi ||
335+
(!win_x64_gnu && !linux_s390x) {
330336
arg.ignore();
331337
}
332338
}
@@ -511,6 +517,7 @@ impl FnType {
511517
"mips64" => cabi_mips64::compute_abi_info(ccx, self),
512518
"powerpc" => cabi_powerpc::compute_abi_info(ccx, self),
513519
"powerpc64" => cabi_powerpc64::compute_abi_info(ccx, self),
520+
"s390x" => cabi_s390x::compute_abi_info(ccx, self),
514521
"asmjs" => cabi_asmjs::compute_abi_info(ccx, self),
515522
a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
516523
}

src/librustc_trans/cabi_s390x.rs

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// FIXME: The assumes we're using the non-vector ABI, i.e. compiling
12+
// for a pre-z13 machine or using -mno-vx.
13+
14+
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
15+
use abi::{FnType, ArgType};
16+
use context::CrateContext;
17+
use type_::Type;
18+
19+
use std::cmp;
20+
21+
fn align_up_to(off: usize, a: usize) -> usize {
22+
return (off + a - 1) / a * a;
23+
}
24+
25+
fn align(off: usize, ty: Type) -> usize {
26+
let a = ty_align(ty);
27+
return align_up_to(off, a);
28+
}
29+
30+
fn ty_align(ty: Type) -> usize {
31+
match ty.kind() {
32+
Integer => ((ty.int_width() as usize) + 7) / 8,
33+
Pointer => 8,
34+
Float => 4,
35+
Double => 8,
36+
Struct => {
37+
if ty.is_packed() {
38+
1
39+
} else {
40+
let str_tys = ty.field_types();
41+
str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t)))
42+
}
43+
}
44+
Array => {
45+
let elt = ty.element_type();
46+
ty_align(elt)
47+
}
48+
Vector => ty_size(ty),
49+
_ => bug!("ty_align: unhandled type")
50+
}
51+
}
52+
53+
fn ty_size(ty: Type) -> usize {
54+
match ty.kind() {
55+
Integer => ((ty.int_width() as usize) + 7) / 8,
56+
Pointer => 8,
57+
Float => 4,
58+
Double => 8,
59+
Struct => {
60+
if ty.is_packed() {
61+
let str_tys = ty.field_types();
62+
str_tys.iter().fold(0, |s, t| s + ty_size(*t))
63+
} else {
64+
let str_tys = ty.field_types();
65+
let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
66+
align(size, ty)
67+
}
68+
}
69+
Array => {
70+
let len = ty.array_length();
71+
let elt = ty.element_type();
72+
let eltsz = ty_size(elt);
73+
len * eltsz
74+
}
75+
Vector => {
76+
let len = ty.vector_length();
77+
let elt = ty.element_type();
78+
let eltsz = ty_size(elt);
79+
len * eltsz
80+
}
81+
_ => bug!("ty_size: unhandled type")
82+
}
83+
}
84+
85+
fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
86+
if is_reg_ty(ret.ty) {
87+
ret.extend_integer_width_to(64);
88+
} else {
89+
ret.make_indirect(ccx);
90+
}
91+
}
92+
93+
fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
94+
if arg.ty.kind() == Struct {
95+
fn is_single_fp_element(tys: &[Type]) -> bool {
96+
if tys.len() != 1 {
97+
return false;
98+
}
99+
match tys[0].kind() {
100+
Float | Double => true,
101+
Struct => is_single_fp_element(&tys[0].field_types()),
102+
_ => false
103+
}
104+
}
105+
106+
if is_single_fp_element(&arg.ty.field_types()) {
107+
match ty_size(arg.ty) {
108+
4 => arg.cast = Some(Type::f32(ccx)),
109+
8 => arg.cast = Some(Type::f64(ccx)),
110+
_ => arg.make_indirect(ccx)
111+
}
112+
} else {
113+
match ty_size(arg.ty) {
114+
1 => arg.cast = Some(Type::i8(ccx)),
115+
2 => arg.cast = Some(Type::i16(ccx)),
116+
4 => arg.cast = Some(Type::i32(ccx)),
117+
8 => arg.cast = Some(Type::i64(ccx)),
118+
_ => arg.make_indirect(ccx)
119+
}
120+
}
121+
return;
122+
}
123+
124+
if is_reg_ty(arg.ty) {
125+
arg.extend_integer_width_to(64);
126+
} else {
127+
arg.make_indirect(ccx);
128+
}
129+
}
130+
131+
fn is_reg_ty(ty: Type) -> bool {
132+
match ty.kind() {
133+
Integer
134+
| Pointer
135+
| Float
136+
| Double => ty_size(ty) <= 8,
137+
_ => false
138+
}
139+
}
140+
141+
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
142+
if !fty.ret.is_ignore() {
143+
classify_ret_ty(ccx, &mut fty.ret);
144+
}
145+
146+
for arg in &mut fty.args {
147+
if arg.is_ignore() { continue; }
148+
classify_arg_ty(ccx, arg);
149+
}
150+
}

src/librustc_trans/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ mod cabi_mips;
102102
mod cabi_mips64;
103103
mod cabi_powerpc;
104104
mod cabi_powerpc64;
105+
mod cabi_s390x;
105106
mod cabi_x86;
106107
mod cabi_x86_64;
107108
mod cabi_x86_win64;

src/libstd/env.rs

+6
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ pub mod consts {
662662
/// - mips64
663663
/// - powerpc
664664
/// - powerpc64
665+
/// - s390x
665666
#[stable(feature = "env", since = "1.0.0")]
666667
pub const ARCH: &'static str = super::arch::ARCH;
667668

@@ -942,6 +943,11 @@ mod arch {
942943
pub const ARCH: &'static str = "powerpc64";
943944
}
944945

946+
#[cfg(target_arch = "s390x")]
947+
mod arch {
948+
pub const ARCH: &'static str = "s390x";
949+
}
950+
945951
#[cfg(target_arch = "le32")]
946952
mod arch {
947953
pub const ARCH: &'static str = "le32";

src/libstd/os/linux/raw.rs

+5
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,11 @@ mod arch {
160160
pub use libc::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
161161
}
162162

163+
#[cfg(target_arch = "s390x")]
164+
mod arch {
165+
pub use libc::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
166+
}
167+
163168
#[cfg(target_arch = "aarch64")]
164169
mod arch {
165170
use os::raw::{c_long, c_int};

src/libstd/os/raw.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@
1717
all(target_os = "linux", any(target_arch = "aarch64",
1818
target_arch = "arm",
1919
target_arch = "powerpc",
20-
target_arch = "powerpc64"))))]
20+
target_arch = "powerpc64",
21+
target_arch = "s390x"))))]
2122
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
2223
#[cfg(not(any(target_os = "android",
2324
target_os = "emscripten",
2425
all(target_os = "linux", any(target_arch = "aarch64",
2526
target_arch = "arm",
2627
target_arch = "powerpc",
27-
target_arch = "powerpc64")))))]
28+
target_arch = "powerpc64",
29+
target_arch = "s390x")))))]
2830
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
2931
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
3032
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8;

src/libstd/sys/unix/rand.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,17 @@ mod imp {
4545
target_arch = "arm",
4646
target_arch = "aarch64",
4747
target_arch = "powerpc",
48-
target_arch = "powerpc64")))]
48+
target_arch = "powerpc64",
49+
target_arch = "s390x")))]
4950
fn getrandom(buf: &mut [u8]) -> libc::c_long {
5051
#[cfg(target_arch = "x86_64")]
5152
const NR_GETRANDOM: libc::c_long = 318;
5253
#[cfg(target_arch = "x86")]
5354
const NR_GETRANDOM: libc::c_long = 355;
5455
#[cfg(target_arch = "arm")]
5556
const NR_GETRANDOM: libc::c_long = 384;
57+
#[cfg(target_arch = "s390x")]
58+
const NR_GETRANDOM: libc::c_long = 349;
5659
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
5760
const NR_GETRANDOM: libc::c_long = 359;
5861
#[cfg(target_arch = "aarch64")]
@@ -71,7 +74,8 @@ mod imp {
7174
target_arch = "arm",
7275
target_arch = "aarch64",
7376
target_arch = "powerpc",
74-
target_arch = "powerpc64"))))]
77+
target_arch = "powerpc64",
78+
target_arch = "s390x"))))]
7579
fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }
7680

7781
fn getrandom_fill_bytes(v: &mut [u8]) {
@@ -110,7 +114,8 @@ mod imp {
110114
target_arch = "arm",
111115
target_arch = "aarch64",
112116
target_arch = "powerpc",
113-
target_arch = "powerpc64")))]
117+
target_arch = "powerpc64",
118+
target_arch = "s390x")))]
114119
fn is_getrandom_available() -> bool {
115120
use sync::atomic::{AtomicBool, Ordering};
116121
use sync::Once;
@@ -139,7 +144,8 @@ mod imp {
139144
target_arch = "arm",
140145
target_arch = "aarch64",
141146
target_arch = "powerpc",
142-
target_arch = "powerpc64"))))]
147+
target_arch = "powerpc64",
148+
target_arch = "s390x"))))]
143149
fn is_getrandom_available() -> bool { false }
144150

145151
pub struct OsRng {

src/libunwind/libunwind.rs

+3
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ pub const unwinder_private_data_size: usize = 2;
6262
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
6363
pub const unwinder_private_data_size: usize = 2;
6464

65+
#[cfg(target_arch = "s390x")]
66+
pub const unwinder_private_data_size: usize = 2;
67+
6568
#[cfg(target_arch = "asmjs")]
6669
pub const unwinder_private_data_size: usize = 20;
6770

src/test/compile-fail/asm-bad-clobber.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// ignore-android
1212
// ignore-arm
1313
// ignore-aarch64
14+
// ignore-s390x
1415

1516
#![feature(asm, rustc_attrs)]
1617

0 commit comments

Comments
 (0)