about summary refs log tree commit diff
path: root/compiler/rustc_ast_lowering/src
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-11-25 07:01:37 +0100
committerGitHub <noreply@github.com>2024-11-25 07:01:37 +0100
commit3f86eddf837191f61ab9ca203b5742278f98d758 (patch)
treea9d1ecc598cb4033263ae97e45ade1bd2f135744 /compiler/rustc_ast_lowering/src
parentc5230d1148995a30ad5fd56aacffe3576fc0e95f (diff)
parentc024d8ccdfb462f4e99b54e6c8456fbc4d745752 (diff)
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
Diffstat (limited to 'compiler/rustc_ast_lowering/src')
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs32
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs8
2 files changed, 34 insertions, 6 deletions
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 520274278a1..ff803e50997 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -17,7 +17,8 @@ use super::errors::{
     InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst,
     InvalidAsmTemplateModifierLabel, InvalidAsmTemplateModifierRegClass,
     InvalidAsmTemplateModifierRegClassSub, InvalidAsmTemplateModifierSym, InvalidRegister,
-    InvalidRegisterClass, RegisterClassOnlyClobber, RegisterConflict,
+    InvalidRegisterClass, RegisterClassOnlyClobber, RegisterClassOnlyClobberStable,
+    RegisterConflict,
 };
 use crate::{
     AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, ParamMode,
@@ -61,6 +62,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 .emit();
             }
         }
+        let allow_experimental_reg = self.tcx.features().asm_experimental_reg();
         if asm.options.contains(InlineAsmOptions::ATT_SYNTAX)
             && !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64))
             && !self.tcx.sess.opts.actually_rustdoc
@@ -324,11 +326,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 // means that we disallow passing a value in/out of the asm and
                 // require that the operand name an explicit register, not a
                 // register class.
-                if reg_class.is_clobber_only(asm_arch.unwrap()) && !op.is_clobber() {
-                    self.dcx().emit_err(RegisterClassOnlyClobber {
-                        op_span: op_sp,
-                        reg_class_name: reg_class.name(),
-                    });
+                if reg_class.is_clobber_only(asm_arch.unwrap(), allow_experimental_reg)
+                    && !op.is_clobber()
+                {
+                    if allow_experimental_reg || reg_class.is_clobber_only(asm_arch.unwrap(), true)
+                    {
+                        // always clobber-only
+                        self.dcx().emit_err(RegisterClassOnlyClobber {
+                            op_span: op_sp,
+                            reg_class_name: reg_class.name(),
+                        });
+                    } else {
+                        // clobber-only in stable
+                        self.tcx
+                            .sess
+                            .create_feature_err(
+                                RegisterClassOnlyClobberStable {
+                                    op_span: op_sp,
+                                    reg_class_name: reg_class.name(),
+                                },
+                                sym::asm_experimental_reg,
+                            )
+                            .emit();
+                    }
                     continue;
                 }
 
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index e6a3f939f2d..447af57354f 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -280,6 +280,14 @@ pub(crate) struct RegisterClassOnlyClobber {
 }
 
 #[derive(Diagnostic)]
+#[diag(ast_lowering_register_class_only_clobber_stable)]
+pub(crate) struct RegisterClassOnlyClobberStable {
+    #[primary_span]
+    pub op_span: Span,
+    pub reg_class_name: Symbol,
+}
+
+#[derive(Diagnostic)]
 #[diag(ast_lowering_register_conflict)]
 pub(crate) struct RegisterConflict<'a> {
     #[primary_span]