]> git.lizzy.rs Git - rust.git/blobdiff - src/value_and_place.rs
Make it possible it use value_field for SIMD values stored ByVal
[rust.git] / src / value_and_place.rs
index 4ac81648700f0d3aad063e5baccb277b014d4982..cb23c814b5d2d6bd038c6821a85da12de075e2eb 100644 (file)
@@ -1,6 +1,6 @@
 use crate::prelude::*;
 
-use cranelift::codegen::ir::immediates::Offset32;
+use cranelift_codegen::ir::immediates::Offset32;
 
 fn codegen_field<'tcx>(
     fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
@@ -122,11 +122,14 @@ pub fn load_scalar<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> Val
         let layout = self.1;
         match self.0 {
             CValueInner::ByRef(ptr) => {
-                let scalar = match layout.abi {
-                    layout::Abi::Scalar(ref scalar) => scalar.clone(),
+                let clif_ty = match layout.abi {
+                    layout::Abi::Scalar(ref scalar) => scalar_to_clif_type(fx.tcx, scalar.clone()),
+                    layout::Abi::Vector { ref element, count } => {
+                        scalar_to_clif_type(fx.tcx, element.clone())
+                            .by(u16::try_from(count).unwrap()).unwrap()
+                    }
                     _ => unreachable!(),
                 };
-                let clif_ty = scalar_to_clif_type(fx.tcx, scalar);
                 ptr.load(fx, clif_ty, MemFlags::new())
             }
             CValueInner::ByVal(value) => value,
@@ -164,13 +167,26 @@ pub fn value_field<'a>(
         field: mir::Field,
     ) -> CValue<'tcx> {
         let layout = self.1;
-        let ptr = match self.0 {
-            CValueInner::ByRef(ptr) => ptr,
+        match self.0 {
+            CValueInner::ByVal(val) => {
+                match layout.abi {
+                    layout::Abi::Vector { element: _, count } => {
+                        let count = u8::try_from(count).expect("SIMD type with more than 255 lanes???");
+                        let field = u8::try_from(field.index()).unwrap();
+                        assert!(field < count);
+                        let lane = fx.bcx.ins().extractlane(val, field);
+                        let field_layout = layout.field(&*fx, usize::from(field));
+                        CValue::by_val(lane, field_layout)
+                    }
+                    _ => unreachable!("value_field for ByVal with abi {:?}", layout.abi),
+                }
+            }
+            CValueInner::ByRef(ptr) => {
+                let (field_ptr, field_layout) = codegen_field(fx, ptr, None, layout, field);
+                CValue::by_ref(field_ptr, field_layout)
+            }
             _ => bug!("place_field for {:?}", self),
-        };
-
-        let (field_ptr, field_layout) = codegen_field(fx, ptr, None, layout, field);
-        CValue::by_ref(field_ptr, field_layout)
+        }
     }
 
     pub fn unsize_value<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>, dest: CPlace<'tcx>) {
@@ -308,7 +324,7 @@ pub fn to_cvalue(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> CValue<'t
         match self.inner {
             CPlaceInner::Var(var) => {
                 let val = fx.bcx.use_var(mir_var(var));
-                fx.bcx.set_val_label(val, cranelift::codegen::ir::ValueLabel::from_u32(var.as_u32()));
+                fx.bcx.set_val_label(val, cranelift_codegen::ir::ValueLabel::from_u32(var.as_u32()));
                 CValue::by_val(val, layout)
             }
             CPlaceInner::Addr(ptr, extra) => {
@@ -346,7 +362,18 @@ pub fn to_ptr_maybe_unsized(
     }
 
     pub fn write_cvalue(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>, from: CValue<'tcx>) {
-        use rustc::hir::Mutability::*;
+        #[cfg(debug_assertions)]
+        {
+            use cranelift_codegen::cursor::{Cursor, CursorPosition};
+            let cur_ebb = match fx.bcx.cursor().position() {
+                CursorPosition::After(ebb) => ebb,
+                _ => unreachable!(),
+            };
+            fx.add_comment(
+                fx.bcx.func.layout.last_inst(cur_ebb).unwrap(),
+                format!("write_cvalue: {:?} <- {:?}",self, from),
+            );
+        }
 
         let from_ty = from.layout().ty;
         let to_ty = self.layout().ty;
@@ -357,14 +384,14 @@ fn assert_assignable<'tcx>(
             to_ty: Ty<'tcx>,
         ) {
             match (&from_ty.kind, &to_ty.kind) {
-                (ty::Ref(_, t, Immutable), ty::Ref(_, u, Immutable))
-                | (ty::Ref(_, t, Mutable), ty::Ref(_, u, Immutable))
-                | (ty::Ref(_, t, Mutable), ty::Ref(_, u, Mutable)) => {
+                (ty::Ref(_, t, Mutability::Not), ty::Ref(_, u, Mutability::Not))
+                | (ty::Ref(_, t, Mutability::Mut), ty::Ref(_, u, Mutability::Not))
+                | (ty::Ref(_, t, Mutability::Mut), ty::Ref(_, u, Mutability::Mut)) => {
                     assert_assignable(fx, t, u);
                     // &mut T -> &T is allowed
                     // &'a T -> &'b T is allowed
                 }
-                (ty::Ref(_, _, Immutable), ty::Ref(_, _, Mutable)) => panic!(
+                (ty::Ref(_, _, Mutability::Not), ty::Ref(_, _, Mutability::Mut)) => panic!(
                     "Cant assign value of type {} to place of type {}",
                     from_ty, to_ty
                 ),
@@ -417,7 +444,7 @@ fn assert_assignable<'tcx>(
         let to_ptr = match self.inner {
             CPlaceInner::Var(var) => {
                 let data = from.load_scalar(fx);
-                fx.bcx.set_val_label(data, cranelift::codegen::ir::ValueLabel::from_u32(var.as_u32()));
+                fx.bcx.set_val_label(data, cranelift_codegen::ir::ValueLabel::from_u32(var.as_u32()));
                 fx.bcx.def_var(mir_var(var), data);
                 return;
             }