diff options
| author | bjorn3 <bjorn3@users.noreply.github.com> | 2021-12-03 12:13:41 +0100 |
|---|---|---|
| committer | bjorn3 <bjorn3@users.noreply.github.com> | 2021-12-03 12:13:41 +0100 |
| commit | dd288d27de23e2f2180e71b6e9b36789ba388e6f (patch) | |
| tree | 1a0f9b0a2eecc049ba2e74b6a43e93af08550bf4 | |
| parent | 516b478c8161c7a90e604f96d0f5878990550f21 (diff) | |
| download | rust-dd288d27de23e2f2180e71b6e9b36789ba388e6f.tar.gz rust-dd288d27de23e2f2180e71b6e9b36789ba388e6f.zip | |
Fix vector types containing an array field with mir opts enabled
| -rw-r--r-- | src/value_and_place.rs | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/src/value_and_place.rs b/src/value_and_place.rs index b13dc54653b..d5c7e2cc297 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -510,6 +510,26 @@ impl<'tcx> CPlace<'tcx> { let dst_layout = self.layout(); let to_ptr = match self.inner { CPlaceInner::Var(_local, var) => { + if let ty::Array(element, len) = dst_layout.ty.kind() { + // Can only happen for vector types + let len = + u16::try_from(len.eval_usize(fx.tcx, ParamEnv::reveal_all())).unwrap(); + let vector_ty = fx.clif_type(element).unwrap().by(len).unwrap(); + + let data = match from.0 { + CValueInner::ByRef(ptr, None) => { + let mut flags = MemFlags::new(); + flags.set_notrap(); + ptr.load(fx, vector_ty, flags) + } + CValueInner::ByVal(_) + | CValueInner::ByValPair(_, _) + | CValueInner::ByRef(_, Some(_)) => bug!("array should be ByRef"), + }; + + fx.bcx.def_var(var, data); + return; + } let data = CValue(from.0, dst_layout).load_scalar(fx); let dst_ty = fx.clif_type(self.layout().ty).unwrap(); transmute_value(fx, var, data, dst_ty); @@ -603,14 +623,39 @@ impl<'tcx> CPlace<'tcx> { let layout = self.layout(); match self.inner { - CPlaceInner::Var(local, var) => { - if let Abi::Vector { .. } = layout.abi { + CPlaceInner::Var(local, var) => match layout.ty.kind() { + ty::Array(_, _) => { + // Can only happen for vector types return CPlace { inner: CPlaceInner::VarLane(local, var, field.as_u32().try_into().unwrap()), layout: layout.field(fx, field.as_u32().try_into().unwrap()), }; } - } + ty::Adt(adt_def, substs) if layout.ty.is_simd() => { + let f0_ty = adt_def.non_enum_variant().fields[0].ty(fx.tcx, substs); + + match f0_ty.kind() { + ty::Array(_, _) => { + assert_eq!(field.as_u32(), 0); + return CPlace { + inner: CPlaceInner::Var(local, var), + layout: layout.field(fx, field.as_u32().try_into().unwrap()), + }; + } + _ => { + return CPlace { + inner: CPlaceInner::VarLane( + local, + var, + field.as_u32().try_into().unwrap(), + ), + layout: layout.field(fx, field.as_u32().try_into().unwrap()), + }; + } + } + } + _ => {} + }, CPlaceInner::VarPair(local, var1, var2) => { let layout = layout.field(&*fx, field.index()); |
