Rollup merge of #131664 - taiki-e:s390x-asm-vreg-inout, r=Amanieu
Support input/output in vector registers of s390x inline assembly (under asm_experimental_reg feature) This extends currently clobber-only vector registers (`vreg`) support to allow passing `#[repr(simd)]` types, floats (f32/f64/f128), and integers (i32/i64/i128) as input/output. This is unstable and gated under new `#![feature(asm_experimental_reg)]` (tracking issue: https://github.com/rust-lang/rust/issues/133416). If the feature is not enabled, only clober is supported as before. | Architecture | Register class | Target feature | Allowed types | | ------------ | -------------- | -------------- | -------------- | | s390x | `vreg` | `vector` | `i32`, `f32`, `i64`, `f64`, `i128`, `f128`, `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | This matches the list of types that are supported by the vector registers in LLVM: https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L301-L313 In addition to `core::simd` types and floats listed above, custom `#[repr(simd)]` types of the same size and type are also allowed. All allowed types other than i32/f32/i64/f64/i128, and relevant target features are currently unstable. Currently there is no SIMD type for s390x in `core::arch`, but this is tracked in https://github.com/rust-lang/rust/issues/130869. cc https://github.com/rust-lang/rust/issues/130869 about vector facility support in s390x cc https://github.com/rust-lang/rust/issues/125398 & https://github.com/rust-lang/rust/issues/116909 about f128 support in asm `@rustbot` label +O-SystemZ +A-inline-assembly
This commit is contained in:
commit
3f86eddf83
22 changed files with 1382 additions and 146 deletions
|
@ -431,6 +431,9 @@ hir_analysis_recursive_generic_parameter = {$param_def_kind} `{$param_name}` is
|
|||
hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}`
|
||||
.note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}`
|
||||
|
||||
hir_analysis_register_type_unstable =
|
||||
type `{$ty}` cannot be used with this register class in stable
|
||||
|
||||
hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}`
|
||||
|
||||
hir_analysis_return_type_notation_equality_bound =
|
||||
|
|
|
@ -7,12 +7,14 @@ use rustc_hir::{self as hir, LangItem};
|
|||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::{Symbol, sym};
|
||||
use rustc_target::asm::{
|
||||
InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType, ModifierInfo,
|
||||
};
|
||||
|
||||
use crate::errors::RegisterTypeUnstable;
|
||||
|
||||
pub struct InlineAsmCtxt<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
typing_env: ty::TypingEnv<'tcx>,
|
||||
|
@ -218,17 +220,29 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
// Check the type against the list of types supported by the selected
|
||||
// register class.
|
||||
let asm_arch = self.tcx.sess.asm_arch.unwrap();
|
||||
let allow_experimental_reg = self.tcx.features().asm_experimental_reg();
|
||||
let reg_class = reg.reg_class();
|
||||
let supported_tys = reg_class.supported_types(asm_arch);
|
||||
let supported_tys = reg_class.supported_types(asm_arch, allow_experimental_reg);
|
||||
let Some((_, feature)) = supported_tys.iter().find(|&&(t, _)| t == asm_ty) else {
|
||||
let msg = format!("type `{ty}` cannot be used with this register class");
|
||||
let mut err = self.tcx.dcx().struct_span_err(expr.span, msg);
|
||||
let supported_tys: Vec<_> = supported_tys.iter().map(|(t, _)| t.to_string()).collect();
|
||||
err.note(format!(
|
||||
"register class `{}` supports these types: {}",
|
||||
reg_class.name(),
|
||||
supported_tys.join(", "),
|
||||
));
|
||||
let mut err = if !allow_experimental_reg
|
||||
&& reg_class.supported_types(asm_arch, true).iter().any(|&(t, _)| t == asm_ty)
|
||||
{
|
||||
self.tcx.sess.create_feature_err(
|
||||
RegisterTypeUnstable { span: expr.span, ty },
|
||||
sym::asm_experimental_reg,
|
||||
)
|
||||
} else {
|
||||
let msg = format!("type `{ty}` cannot be used with this register class");
|
||||
let mut err = self.tcx.dcx().struct_span_err(expr.span, msg);
|
||||
let supported_tys: Vec<_> =
|
||||
supported_tys.iter().map(|(t, _)| t.to_string()).collect();
|
||||
err.note(format!(
|
||||
"register class `{}` supports these types: {}",
|
||||
reg_class.name(),
|
||||
supported_tys.join(", "),
|
||||
));
|
||||
err
|
||||
};
|
||||
if let Some(suggest) = reg_class.suggest_class(asm_arch, asm_ty) {
|
||||
err.help(format!("consider using the `{}` register class instead", suggest.name()));
|
||||
}
|
||||
|
@ -313,6 +327,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
self.tcx.dcx().delayed_bug("target architecture does not support asm");
|
||||
return;
|
||||
};
|
||||
let allow_experimental_reg = self.tcx.features().asm_experimental_reg();
|
||||
for (idx, (op, op_sp)) in asm.operands.iter().enumerate() {
|
||||
// Validate register classes against currently enabled target
|
||||
// features. We check that at least one type is available for
|
||||
|
@ -352,7 +367,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
if let InlineAsmRegClass::Err = reg_class {
|
||||
continue;
|
||||
}
|
||||
for &(_, feature) in reg_class.supported_types(asm_arch) {
|
||||
for &(_, feature) in reg_class.supported_types(asm_arch, allow_experimental_reg)
|
||||
{
|
||||
match feature {
|
||||
Some(feature) => {
|
||||
if target_features.contains(&feature) {
|
||||
|
|
|
@ -1708,3 +1708,11 @@ pub(crate) struct CmseEntryGeneric {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_register_type_unstable)]
|
||||
pub(crate) struct RegisterTypeUnstable<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub ty: Ty<'a>,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue