Skip to content

Commit 7656805

Browse files
committed
Support s390x z13 vector ABI
1 parent f496659 commit 7656805

File tree

10 files changed

+280
-27
lines changed

10 files changed

+280
-27
lines changed

Diff for: compiler/rustc_codegen_gcc/src/builder.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use rustc_middle::ty::{Instance, ParamEnv, Ty, TyCtxt};
3030
use rustc_span::Span;
3131
use rustc_span::def_id::DefId;
3232
use rustc_target::abi::call::FnAbi;
33-
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, Target, WasmCAbi};
33+
use rustc_target::spec::{HasS390xVector, HasTargetSpec, HasWasmCAbiOpt, Target, WasmCAbi};
3434

3535
use crate::common::{SignType, TypeReflection, type_is_pointer};
3636
use crate::context::CodegenCx;
@@ -2347,6 +2347,12 @@ impl<'tcx> HasWasmCAbiOpt for Builder<'_, '_, 'tcx> {
23472347
}
23482348
}
23492349

2350+
impl<'tcx> HasS390xVector for Builder<'_, '_, 'tcx> {
2351+
fn has_s390x_vector(&self) -> bool {
2352+
self.cx.has_s390x_vector()
2353+
}
2354+
}
2355+
23502356
pub trait ToGccComp {
23512357
fn to_gcc_comparison(&self) -> ComparisonOp;
23522358
}

Diff for: compiler/rustc_codegen_gcc/src/context.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ use rustc_session::Session;
1919
use rustc_span::source_map::respan;
2020
use rustc_span::{DUMMY_SP, Span};
2121
use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
22-
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, Target, TlsModel, WasmCAbi};
22+
use rustc_target::spec::{
23+
HasS390xVector, HasTargetSpec, HasWasmCAbiOpt, Target, TlsModel, WasmCAbi,
24+
};
2325

2426
use crate::callee::get_fn;
2527
use crate::common::SignType;
@@ -538,6 +540,13 @@ impl<'gcc, 'tcx> HasWasmCAbiOpt for CodegenCx<'gcc, 'tcx> {
538540
}
539541
}
540542

543+
impl<'gcc, 'tcx> HasS390xVector for CodegenCx<'gcc, 'tcx> {
544+
fn has_s390x_vector(&self) -> bool {
545+
// `unstable_target_features` is used here because "vector" is gated behind s390x_target_feature.
546+
self.tcx.sess.unstable_target_features.contains(&sym::vector)
547+
}
548+
}
549+
541550
impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
542551
#[inline]
543552
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {

Diff for: compiler/rustc_middle/src/ty/layout.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
2121
use rustc_target::abi::call::FnAbi;
2222
use rustc_target::abi::{FieldIdx, TyAbiInterface, VariantIdx, call};
2323
use rustc_target::spec::abi::Abi as SpecAbi;
24-
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, PanicStrategy, Target, WasmCAbi};
24+
use rustc_target::spec::{
25+
HasS390xVector, HasTargetSpec, HasWasmCAbiOpt, PanicStrategy, Target, WasmCAbi,
26+
};
2527
use tracing::debug;
2628
use {rustc_abi as abi, rustc_hir as hir};
2729

@@ -544,6 +546,13 @@ impl<'tcx> HasWasmCAbiOpt for TyCtxt<'tcx> {
544546
}
545547
}
546548

549+
impl<'tcx> HasS390xVector for TyCtxt<'tcx> {
550+
fn has_s390x_vector(&self) -> bool {
551+
// `unstable_target_features` is used here because "vector" is gated behind s390x_target_feature.
552+
self.sess.unstable_target_features.contains(&sym::vector)
553+
}
554+
}
555+
547556
impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> {
548557
#[inline]
549558
fn tcx(&self) -> TyCtxt<'tcx> {
@@ -595,6 +604,12 @@ impl<'tcx> HasWasmCAbiOpt for LayoutCx<'tcx> {
595604
}
596605
}
597606

607+
impl<'tcx> HasS390xVector for LayoutCx<'tcx> {
608+
fn has_s390x_vector(&self) -> bool {
609+
self.calc.cx.has_s390x_vector()
610+
}
611+
}
612+
598613
impl<'tcx> HasTyCtxt<'tcx> for LayoutCx<'tcx> {
599614
fn tcx(&self) -> TyCtxt<'tcx> {
600615
self.calc.cx

Diff for: compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2126,6 +2126,7 @@ symbols! {
21262126
vec_pop,
21272127
vec_with_capacity,
21282128
vecdeque_iter,
2129+
vector,
21292130
version,
21302131
vfp2,
21312132
vis,

Diff for: compiler/rustc_target/src/abi/call/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_macros::HashStable_Generic;
55
use rustc_span::Symbol;
66

77
use crate::abi::{self, Abi, Align, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
8-
use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt, WasmCAbi};
8+
use crate::spec::{self, HasS390xVector, HasTargetSpec, HasWasmCAbiOpt, WasmCAbi};
99

1010
mod aarch64;
1111
mod amdgpu;
@@ -876,7 +876,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
876876
) -> Result<(), AdjustForForeignAbiError>
877877
where
878878
Ty: TyAbiInterface<'a, C> + Copy,
879-
C: HasDataLayout + HasTargetSpec + HasWasmCAbiOpt,
879+
C: HasDataLayout + HasTargetSpec + HasWasmCAbiOpt + HasS390xVector,
880880
{
881881
if abi == spec::abi::Abi::X86Interrupt {
882882
if let Some(arg) = self.args.first_mut() {

Diff for: compiler/rustc_target/src/abi/call/s390x.rs

+51-16
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,46 @@
1-
// FIXME: The assumes we're using the non-vector ABI, i.e., compiling
2-
// for a pre-z13 machine or using -mno-vx.
1+
use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind};
2+
use crate::abi::{Abi, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
3+
use crate::spec::{HasS390xVector, HasTargetSpec};
34

4-
use crate::abi::call::{ArgAbi, FnAbi, Reg};
5-
use crate::abi::{HasDataLayout, TyAbiInterface};
6-
use crate::spec::HasTargetSpec;
5+
#[derive(Debug, Clone, Copy, PartialEq)]
6+
enum ABI {
7+
NoVector, // no-vector ABI, i.e., compiling for a pre-z13 machine or using -C target-feature=-vector
8+
Vector, // vector ABI, i.e., compiling for a z13 or later machine or using -C target-feature=+vector
9+
}
10+
use ABI::*;
711

8-
fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
9-
if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 {
12+
fn contains_vector<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>, expected_size: Size) -> bool
13+
where
14+
Ty: TyAbiInterface<'a, C> + Copy,
15+
{
16+
match layout.abi {
17+
Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) => false,
18+
Abi::Vector { .. } => layout.size == expected_size,
19+
Abi::Aggregate { .. } => {
20+
for i in 0..layout.fields.count() {
21+
if contains_vector(cx, layout.field(cx, i), expected_size) {
22+
return true;
23+
}
24+
}
25+
false
26+
}
27+
}
28+
}
29+
30+
fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>, abi: ABI) {
31+
let size = ret.layout.size;
32+
if abi == Vector && size.bits() <= 128 && matches!(ret.layout.abi, Abi::Vector { .. }) {
33+
ret.cast_to(Reg { kind: RegKind::Vector, size }); // FIXME: this cast is unneeded?
34+
return;
35+
}
36+
if !ret.layout.is_aggregate() && size.bits() <= 64 {
1037
ret.extend_integer_width_to(64);
11-
} else {
12-
ret.make_indirect();
38+
return;
1339
}
40+
ret.make_indirect();
1441
}
1542

16-
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
43+
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI)
1744
where
1845
Ty: TyAbiInterface<'a, C> + Copy,
1946
C: HasDataLayout + HasTargetSpec,
@@ -32,19 +59,25 @@ where
3259
}
3360
return;
3461
}
35-
if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {
62+
63+
let size = arg.layout.size;
64+
if abi == Vector && size.bits() <= 128 && contains_vector(cx, arg.layout, size) {
65+
arg.cast_to(Reg { kind: RegKind::Vector, size });
66+
return;
67+
}
68+
if !arg.layout.is_aggregate() && size.bits() <= 64 {
3669
arg.extend_integer_width_to(64);
3770
return;
3871
}
3972

4073
if arg.layout.is_single_fp_element(cx) {
41-
match arg.layout.size.bytes() {
74+
match size.bytes() {
4275
4 => arg.cast_to(Reg::f32()),
4376
8 => arg.cast_to(Reg::f64()),
4477
_ => arg.make_indirect(),
4578
}
4679
} else {
47-
match arg.layout.size.bytes() {
80+
match size.bytes() {
4881
1 => arg.cast_to(Reg::i8()),
4982
2 => arg.cast_to(Reg::i16()),
5083
4 => arg.cast_to(Reg::i32()),
@@ -57,13 +90,15 @@ where
5790
pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
5891
where
5992
Ty: TyAbiInterface<'a, C> + Copy,
60-
C: HasDataLayout + HasTargetSpec,
93+
C: HasDataLayout + HasTargetSpec + HasS390xVector,
6194
{
95+
let abi = if cx.has_s390x_vector() { Vector } else { NoVector };
96+
6297
if !fn_abi.ret.is_ignore() {
63-
classify_ret(&mut fn_abi.ret);
98+
classify_ret(&mut fn_abi.ret, abi);
6499
}
65100

66101
for arg in fn_abi.args.iter_mut() {
67-
classify_arg(cx, arg);
102+
classify_arg(cx, arg, abi);
68103
}
69104
}

Diff for: compiler/rustc_target/src/spec/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2096,6 +2096,10 @@ pub trait HasWasmCAbiOpt {
20962096
fn wasm_c_abi_opt(&self) -> WasmCAbi;
20972097
}
20982098

2099+
pub trait HasS390xVector {
2100+
fn has_s390x_vector(&self) -> bool;
2101+
}
2102+
20992103
type StaticCow<T> = Cow<'static, T>;
21002104

21012105
/// Optional aspects of a target specification.

Diff for: compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs

-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ pub(crate) fn target() -> Target {
66
base.endian = Endian::Big;
77
// z10 is the oldest CPU supported by LLVM
88
base.cpu = "z10".into();
9-
// FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector
10-
// ABI. Pass the -vector feature string to LLVM to respect this assumption.
11-
base.features = "-vector".into();
129
base.max_atomic_width = Some(128);
1310
base.min_global_align = Some(16);
1411
base.stack_probes = StackProbeType::Inline;

Diff for: compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs

-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ pub(crate) fn target() -> Target {
66
base.endian = Endian::Big;
77
// z10 is the oldest CPU supported by LLVM
88
base.cpu = "z10".into();
9-
// FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector
10-
// ABI. Pass the -vector feature string to LLVM to respect this assumption.
11-
base.features = "-vector".into();
129
base.max_atomic_width = Some(128);
1310
base.min_global_align = Some(16);
1411
base.static_position_independent_executables = true;

0 commit comments

Comments
 (0)