]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_codegen_ssa/mir/operand.rs
Rollup merge of #61389 - Zoxc:arena-cleanup, r=eddyb
[rust.git] / src / librustc_codegen_ssa / mir / operand.rs
index 3b8e5b449538324c522328192b3bd61d470ba74c..0ae2fbe8071adb5787ae3a228094ef4ddacca1af 100644 (file)
@@ -1,7 +1,7 @@
-use rustc::mir::interpret::{ConstValue, ErrorHandled};
+use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar};
 use rustc::mir;
 use rustc::ty;
-use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
+use rustc::ty::layout::{self, Align, LayoutOf, TyLayout, Size};
 
 use crate::base;
 use crate::MemFlags;
@@ -67,12 +67,12 @@ pub fn new_zst<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
 
     pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         bx: &mut Bx,
-        val: ty::Const<'tcx>
-    ) -> Result<Self, ErrorHandled> {
+        val: &'tcx ty::Const<'tcx>
+    ) -> Self {
         let layout = bx.layout_of(val.ty);
 
         if layout.is_zst() {
-            return Ok(OperandRef::new_zst(bx, layout));
+            return OperandRef::new_zst(bx, layout);
         }
 
         let val = match val.val {
@@ -92,28 +92,32 @@ pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
                 );
                 OperandValue::Immediate(llval)
             },
-            ConstValue::Slice(a, b) => {
+            ConstValue::Slice { data, start, end } => {
                 let a_scalar = match layout.abi {
                     layout::Abi::ScalarPair(ref a, _) => a,
                     _ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout)
                 };
+                let a = Scalar::from(Pointer::new(
+                    bx.tcx().alloc_map.lock().allocate(data),
+                    Size::from_bytes(start as u64),
+                )).into();
                 let a_llval = bx.scalar_to_backend(
                     a,
                     a_scalar,
                     bx.scalar_pair_element_backend_type(layout, 0, true),
                 );
-                let b_llval = bx.const_usize(b);
+                let b_llval = bx.const_usize((end - start) as u64);
                 OperandValue::Pair(a_llval, b_llval)
             },
             ConstValue::ByRef(ptr, alloc) => {
-                return Ok(bx.load_operand(bx.from_const_alloc(layout, alloc, ptr.offset)));
+                return bx.load_operand(bx.from_const_alloc(layout, alloc, ptr.offset));
             },
         };
 
-        Ok(OperandRef {
+        OperandRef {
             val,
             layout
-        })
+        }
     }
 
     /// Asserts that this operand refers to a scalar and returns
@@ -380,45 +384,47 @@ fn maybe_codegen_consume_direct(
     ) -> Option<OperandRef<'tcx, Bx::Value>> {
         debug!("maybe_codegen_consume_direct(place={:?})", place);
 
-        // watch out for locals that do not have an
-        // alloca; they are handled somewhat differently
-        if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
-            match self.locals[index] {
-                LocalRef::Operand(Some(o)) => {
-                    return Some(o);
-                }
-                LocalRef::Operand(None) => {
-                    bug!("use of {:?} before def", place);
-                }
-                LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
-                    // use path below
-                }
-            }
-        }
+        place.iterate(|place_base, place_projection| {
+            if let mir::PlaceBase::Local(index) = place_base {
+                match self.locals[*index] {
+                    LocalRef::Operand(Some(mut o)) => {
+                        // Moves out of scalar and scalar pair fields are trivial.
+                        for proj in place_projection {
+                            match proj.elem {
+                                mir::ProjectionElem::Field(ref f, _) => {
+                                    o = o.extract_field(bx, f.index());
+                                }
+                                mir::ProjectionElem::Index(_) |
+                                mir::ProjectionElem::ConstantIndex { .. } => {
+                                    // ZSTs don't require any actual memory access.
+                                    // FIXME(eddyb) deduplicate this with the identical
+                                    // checks in `codegen_consume` and `extract_field`.
+                                    let elem = o.layout.field(bx.cx(), 0);
+                                    if elem.is_zst() {
+                                        o = OperandRef::new_zst(bx, elem);
+                                    } else {
+                                        return None;
+                                    }
+                                }
+                                _ => return None,
+                            }
+                        }
 
-        // Moves out of scalar and scalar pair fields are trivial.
-        if let &mir::Place::Projection(ref proj) = place {
-            if let Some(o) = self.maybe_codegen_consume_direct(bx, &proj.base) {
-                match proj.elem {
-                    mir::ProjectionElem::Field(ref f, _) => {
-                        return Some(o.extract_field(bx, f.index()));
+                        Some(o)
                     }
-                    mir::ProjectionElem::Index(_) |
-                    mir::ProjectionElem::ConstantIndex { .. } => {
-                        // ZSTs don't require any actual memory access.
-                        // FIXME(eddyb) deduplicate this with the identical
-                        // checks in `codegen_consume` and `extract_field`.
-                        let elem = o.layout.field(bx.cx(), 0);
-                        if elem.is_zst() {
-                            return Some(OperandRef::new_zst(bx, elem));
-                        }
+                    LocalRef::Operand(None) => {
+                        bug!("use of {:?} before def", place);
+                    }
+                    LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
+                        // watch out for locals that do not have an
+                        // alloca; they are handled somewhat differently
+                        None
                     }
-                    _ => {}
                 }
+            } else {
+                None
             }
-        }
-
-        None
+        })
     }
 
     pub fn codegen_consume(
@@ -462,7 +468,7 @@ pub fn codegen_operand(
             mir::Operand::Constant(ref constant) => {
                 let ty = self.monomorphize(&constant.ty);
                 self.eval_mir_constant(constant)
-                    .and_then(|c| OperandRef::from_const(bx, c))
+                    .map(|c| OperandRef::from_const(bx, c))
                     .unwrap_or_else(|err| {
                         match err {
                             // errored or at least linted