Skip to content

Commit

Permalink
Support s390x z13 vector ABI
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Oct 12, 2024
1 parent 8f8bee4 commit c14d9b2
Show file tree
Hide file tree
Showing 10 changed files with 322 additions and 27 deletions.
8 changes: 7 additions & 1 deletion compiler/rustc_codegen_gcc/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use rustc_middle::ty::{Instance, ParamEnv, Ty, TyCtxt};
use rustc_span::Span;
use rustc_span::def_id::DefId;
use rustc_target::abi::call::FnAbi;
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, Target, WasmCAbi};
use rustc_target::spec::{HasS390xVector, HasTargetSpec, HasWasmCAbiOpt, Target, WasmCAbi};

use crate::common::{SignType, TypeReflection, type_is_pointer};
use crate::context::CodegenCx;
Expand Down Expand Up @@ -2347,6 +2347,12 @@ impl<'tcx> HasWasmCAbiOpt for Builder<'_, '_, 'tcx> {
}
}

impl<'tcx> HasS390xVector for Builder<'_, '_, 'tcx> {
fn has_s390x_vector(&self) -> bool {
self.cx.has_s390x_vector()
}
}

pub trait ToGccComp {
fn to_gcc_comparison(&self) -> ComparisonOp;
}
Expand Down
12 changes: 11 additions & 1 deletion compiler/rustc_codegen_gcc/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ use rustc_middle::ty::layout::{
use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
use rustc_session::Session;
use rustc_span::source_map::respan;
use rustc_span::symbol::sym;
use rustc_span::{DUMMY_SP, Span};
use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, Target, TlsModel, WasmCAbi};
use rustc_target::spec::{
HasS390xVector, HasTargetSpec, HasWasmCAbiOpt, Target, TlsModel, WasmCAbi,
};

use crate::callee::get_fn;
use crate::common::SignType;
Expand Down Expand Up @@ -538,6 +541,13 @@ impl<'gcc, 'tcx> HasWasmCAbiOpt for CodegenCx<'gcc, 'tcx> {
}
}

impl<'gcc, 'tcx> HasS390xVector for CodegenCx<'gcc, 'tcx> {
fn has_s390x_vector(&self) -> bool {
// `unstable_target_features` is used here because "vector" is gated behind s390x_target_feature.
self.tcx.sess.unstable_target_features.contains(&sym::vector)
}
}

impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
#[inline]
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
Expand Down
17 changes: 16 additions & 1 deletion compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::{FieldIdx, TyAbiInterface, VariantIdx, call};
use rustc_target::spec::abi::Abi as SpecAbi;
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, PanicStrategy, Target, WasmCAbi};
use rustc_target::spec::{
HasS390xVector, HasTargetSpec, HasWasmCAbiOpt, PanicStrategy, Target, WasmCAbi,
};
use tracing::debug;
use {rustc_abi as abi, rustc_hir as hir};

Expand Down Expand Up @@ -544,6 +546,13 @@ impl<'tcx> HasWasmCAbiOpt for TyCtxt<'tcx> {
}
}

impl<'tcx> HasS390xVector for TyCtxt<'tcx> {
fn has_s390x_vector(&self) -> bool {
// `unstable_target_features` is used here because "vector" is gated behind s390x_target_feature.
self.sess.unstable_target_features.contains(&sym::vector)
}
}

impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> {
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> {
Expand Down Expand Up @@ -595,6 +604,12 @@ impl<'tcx> HasWasmCAbiOpt for LayoutCx<'tcx> {
}
}

impl<'tcx> HasS390xVector for LayoutCx<'tcx> {
fn has_s390x_vector(&self) -> bool {
self.calc.cx.has_s390x_vector()
}
}

impl<'tcx> HasTyCtxt<'tcx> for LayoutCx<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.calc.cx
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2130,6 +2130,7 @@ symbols! {
vec_pop,
vec_with_capacity,
vecdeque_iter,
vector,
version,
vfp2,
vis,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_target/src/abi/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;

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

mod aarch64;
mod amdgpu;
Expand Down Expand Up @@ -876,7 +876,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
) -> Result<(), AdjustForForeignAbiError>
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout + HasTargetSpec + HasWasmCAbiOpt,
C: HasDataLayout + HasTargetSpec + HasWasmCAbiOpt + HasS390xVector,
{
if abi == spec::abi::Abi::X86Interrupt {
if let Some(arg) = self.args.first_mut() {
Expand Down
67 changes: 51 additions & 16 deletions compiler/rustc_target/src/abi/call/s390x.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,46 @@
// FIXME: The assumes we're using the non-vector ABI, i.e., compiling
// for a pre-z13 machine or using -mno-vx.
use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind};
use crate::abi::{Abi, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
use crate::spec::{HasS390xVector, HasTargetSpec};

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

fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 {
fn contains_vector<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>, expected_size: Size) -> bool
where
Ty: TyAbiInterface<'a, C> + Copy,
{
match layout.abi {
Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) => false,
Abi::Vector { .. } => layout.size == expected_size,
Abi::Aggregate { .. } => {
for i in 0..layout.fields.count() {
if contains_vector(cx, layout.field(cx, i), expected_size) {
return true;
}
}
false
}
}
}

fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>, abi: ABI) {
let size = ret.layout.size;
if abi == Vector && size.bits() <= 128 && matches!(ret.layout.abi, Abi::Vector { .. }) {
ret.cast_to(Reg { kind: RegKind::Vector, size }); // FIXME: this cast is unneeded?
return;
}
if !ret.layout.is_aggregate() && size.bits() <= 64 {
ret.extend_integer_width_to(64);
} else {
ret.make_indirect();
return;
}
ret.make_indirect();
}

fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout + HasTargetSpec,
Expand All @@ -32,19 +59,25 @@ where
}
return;
}
if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {

let size = arg.layout.size;
if abi == Vector && size.bits() <= 128 && contains_vector(cx, arg.layout, size) {
arg.cast_to(Reg { kind: RegKind::Vector, size });
return;
}
if !arg.layout.is_aggregate() && size.bits() <= 64 {
arg.extend_integer_width_to(64);
return;
}

if arg.layout.is_single_fp_element(cx) {
match arg.layout.size.bytes() {
match size.bytes() {
4 => arg.cast_to(Reg::f32()),
8 => arg.cast_to(Reg::f64()),
_ => arg.make_indirect(),
}
} else {
match arg.layout.size.bytes() {
match size.bytes() {
1 => arg.cast_to(Reg::i8()),
2 => arg.cast_to(Reg::i16()),
4 => arg.cast_to(Reg::i32()),
Expand All @@ -57,13 +90,15 @@ where
pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout + HasTargetSpec,
C: HasDataLayout + HasTargetSpec + HasS390xVector,
{
let abi = if cx.has_s390x_vector() { Vector } else { NoVector };

if !fn_abi.ret.is_ignore() {
classify_ret(&mut fn_abi.ret);
classify_ret(&mut fn_abi.ret, abi);
}

for arg in fn_abi.args.iter_mut() {
classify_arg(cx, arg);
classify_arg(cx, arg, abi);
}
}
4 changes: 4 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2096,6 +2096,10 @@ pub trait HasWasmCAbiOpt {
fn wasm_c_abi_opt(&self) -> WasmCAbi;
}

pub trait HasS390xVector {
fn has_s390x_vector(&self) -> bool;
}

type StaticCow<T> = Cow<'static, T>;

/// Optional aspects of a target specification.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ pub(crate) fn target() -> Target {
base.endian = Endian::Big;
// z10 is the oldest CPU supported by LLVM
base.cpu = "z10".into();
// FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector
// ABI. Pass the -vector feature string to LLVM to respect this assumption.
base.features = "-vector".into();
base.max_atomic_width = Some(128);
base.min_global_align = Some(16);
base.stack_probes = StackProbeType::Inline;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ pub(crate) fn target() -> Target {
base.endian = Endian::Big;
// z10 is the oldest CPU supported by LLVM
base.cpu = "z10".into();
// FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector
// ABI. Pass the -vector feature string to LLVM to respect this assumption.
base.features = "-vector".into();
base.max_atomic_width = Some(128);
base.min_global_align = Some(16);
base.static_position_independent_executables = true;
Expand Down
Loading

0 comments on commit c14d9b2

Please sign in to comment.