about summary refs log tree commit diff
path: root/src/librustc_codegen_llvm/mir
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc_codegen_llvm/mir')
-rw-r--r--src/librustc_codegen_llvm/mir/analyze.rs56
-rw-r--r--src/librustc_codegen_llvm/mir/block.rs50
-rw-r--r--src/librustc_codegen_llvm/mir/constant.rs25
-rw-r--r--src/librustc_codegen_llvm/mir/mod.rs3
-rw-r--r--src/librustc_codegen_llvm/mir/operand.rs22
-rw-r--r--src/librustc_codegen_llvm/mir/place.rs24
-rw-r--r--src/librustc_codegen_llvm/mir/statement.rs18
7 files changed, 129 insertions, 69 deletions
diff --git a/src/librustc_codegen_llvm/mir/analyze.rs b/src/librustc_codegen_llvm/mir/analyze.rs
index a0d6cc46295..2af772bd7ce 100644
--- a/src/librustc_codegen_llvm/mir/analyze.rs
+++ b/src/librustc_codegen_llvm/mir/analyze.rs
@@ -15,7 +15,7 @@ use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc::mir::{self, Location, TerminatorKind};
-use rustc::mir::visit::{Visitor, PlaceContext};
+use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
 use rustc::mir::traversal;
 use rustc::ty;
 use rustc::ty::layout::LayoutOf;
@@ -116,7 +116,11 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
                 self.not_ssa(index);
             }
         } else {
-            self.visit_place(place, PlaceContext::Store, location);
+            self.visit_place(
+                place,
+                PlaceContext::MutatingUse(MutatingUseContext::Store),
+                location
+            );
         }
 
         self.visit_rvalue(rvalue, location);
@@ -142,7 +146,11 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
                 // is not guaranteed to be statically dominated by the
                 // definition of x, so x must always be in an alloca.
                 if let mir::Operand::Move(ref place) = args[0] {
-                    self.visit_place(place, PlaceContext::Drop, location);
+                    self.visit_place(
+                        place,
+                        PlaceContext::MutatingUse(MutatingUseContext::Drop),
+                        location
+                    );
                 }
             }
         }
@@ -160,7 +168,8 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
         if let mir::Place::Projection(ref proj) = *place {
             // Allow uses of projections that are ZSTs or from scalar fields.
             let is_consume = match context {
-                PlaceContext::Copy | PlaceContext::Move => true,
+                PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
+                PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
                 _ => false
             };
             if is_consume {
@@ -168,7 +177,9 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
                 let base_ty = self.fx.monomorphize(&base_ty);
 
                 // ZSTs don't require any actual memory access.
-                let elem_ty = base_ty.projection_ty(cx.tcx, &proj.elem).to_ty(cx.tcx);
+                let elem_ty = base_ty
+                    .projection_ty(cx.tcx, &proj.elem)
+                    .to_ty(cx.tcx);
                 let elem_ty = self.fx.monomorphize(&elem_ty);
                 if cx.layout_of(elem_ty).is_zst() {
                     return;
@@ -188,7 +199,11 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
 
             // A deref projection only reads the pointer, never needs the place.
             if let mir::ProjectionElem::Deref = proj.elem {
-                return self.visit_place(&proj.base, PlaceContext::Copy, location);
+                return self.visit_place(
+                    &proj.base,
+                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
+                    location
+                );
             }
         }
 
@@ -200,16 +215,15 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
                    context: PlaceContext<'tcx>,
                    location: Location) {
         match context {
-            PlaceContext::Call => {
+            PlaceContext::MutatingUse(MutatingUseContext::Call) => {
                 self.assign(local, location);
             }
 
-            PlaceContext::StorageLive |
-            PlaceContext::StorageDead |
-            PlaceContext::Validate => {}
+            PlaceContext::NonUse(_) |
+            PlaceContext::MutatingUse(MutatingUseContext::Retag) => {}
 
-            PlaceContext::Copy |
-            PlaceContext::Move => {
+            PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
+            PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => {
                 // Reads from uninitialized variables (e.g. in dead code, after
                 // optimizations) require locals to be in (uninitialized) memory.
                 // NB: there can be uninitialized reads of a local visited after
@@ -225,15 +239,19 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
                 }
             }
 
-            PlaceContext::Inspect |
-            PlaceContext::Store |
-            PlaceContext::AsmOutput |
-            PlaceContext::Borrow { .. } |
-            PlaceContext::Projection(..) => {
+            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) |
+            PlaceContext::MutatingUse(MutatingUseContext::Store) |
+            PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
+            PlaceContext::MutatingUse(MutatingUseContext::Borrow(..)) |
+            PlaceContext::MutatingUse(MutatingUseContext::Projection) |
+            PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) |
+            PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(..)) |
+            PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) |
+            PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => {
                 self.not_ssa(local);
             }
 
-            PlaceContext::Drop => {
+            PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
                 let ty = mir::Place::Local(local).ty(self.fx.mir, self.fx.cx.tcx);
                 let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx));
 
@@ -328,7 +346,7 @@ pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Mir<'tcx>) -> IndexVec<mir::BasicBlock
                        funclet, succ, kind);
                 match kind {
                     CleanupKind::NotCleanup => {
-                        result[succ] = CleanupKind::Internal { funclet: funclet };
+                        result[succ] = CleanupKind::Internal { funclet };
                     }
                     CleanupKind::Funclet => {
                         if funclet != succ {
diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs
index 68e30227185..3f9921a5cf9 100644
--- a/src/librustc_codegen_llvm/mir/block.rs
+++ b/src/librustc_codegen_llvm/mir/block.rs
@@ -298,8 +298,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
                 };
                 let (drop_fn, fn_ty) = match ty.sty {
                     ty::Dynamic(..) => {
-                        let fn_ty = drop_fn.ty(bx.cx.tcx);
-                        let sig = common::ty_fn_sig(bx.cx, fn_ty);
+                        let sig = drop_fn.fn_sig(bx.cx.tcx);
                         let sig = bx.tcx().normalize_erasing_late_bound_regions(
                             ty::ParamEnv::reveal_all(),
                             &sig,
@@ -643,14 +642,54 @@ impl FunctionCx<'a, 'll, 'tcx> {
                     (&args[..], None)
                 };
 
-                for (i, arg) in first_args.iter().enumerate() {
+                'make_args: for (i, arg) in first_args.iter().enumerate() {
                     let mut op = self.codegen_operand(&bx, arg);
+
                     if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {
-                        if let Pair(data_ptr, meta) = op.val {
+                        if let Pair(..) = op.val {
+                            // In the case of Rc<Self>, we need to explicitly pass a
+                            // *mut RcBox<Self> with a Scalar (not ScalarPair) ABI. This is a hack
+                            // that is understood elsewhere in the compiler as a method on
+                            // `dyn Trait`.
+                            // To get a `*mut RcBox<Self>`, we just keep unwrapping newtypes until
+                            // we get a value of a built-in pointer type
+                            'descend_newtypes: while !op.layout.ty.is_unsafe_ptr()
+                                            && !op.layout.ty.is_region_ptr()
+                            {
+                                'iter_fields: for i in 0..op.layout.fields.count() {
+                                    let field = op.extract_field(&bx, i);
+                                    if !field.layout.is_zst() {
+                                        // we found the one non-zero-sized field that is allowed
+                                        // now find *its* non-zero-sized field, or stop if it's a
+                                        // pointer
+                                        op = field;
+                                        continue 'descend_newtypes
+                                    }
+                                }
+
+                                span_bug!(span, "receiver has no non-zero-sized fields {:?}", op);
+                            }
+
+                            // now that we have `*dyn Trait` or `&dyn Trait`, split it up into its
+                            // data pointer and vtable. Look up the method in the vtable, and pass
+                            // the data pointer as the first argument
+                            match op.val {
+                                Pair(data_ptr, meta) => {
+                                    llfn = Some(meth::VirtualIndex::from_index(idx)
+                                        .get_fn(&bx, meta, &fn_ty));
+                                    llargs.push(data_ptr);
+                                    continue 'make_args
+                                }
+                                other => bug!("expected a Pair, got {:?}", other)
+                            }
+                        } else if let Ref(data_ptr, Some(meta), _) = op.val {
+                            // by-value dynamic dispatch
                             llfn = Some(meth::VirtualIndex::from_index(idx)
                                 .get_fn(&bx, meta, &fn_ty));
                             llargs.push(data_ptr);
                             continue;
+                        } else {
+                            span_bug!(span, "can't codegen a virtual call on {:?}", op);
                         }
                     }
 
@@ -745,7 +784,8 @@ impl FunctionCx<'a, 'll, 'tcx> {
                     // have scary latent bugs around.
 
                     let scratch = PlaceRef::alloca(bx, arg.layout, "arg");
-                    base::memcpy_ty(bx, scratch.llval, llval, op.layout, align, MemFlags::empty());
+                    base::memcpy_ty(bx, scratch.llval, scratch.align, llval, align,
+                                    op.layout, MemFlags::empty());
                     (scratch.llval, scratch.align, true)
                 } else {
                     (llval, align, true)
diff --git a/src/librustc_codegen_llvm/mir/constant.rs b/src/librustc_codegen_llvm/mir/constant.rs
index 9f0f7443890..586a4907740 100644
--- a/src/librustc_codegen_llvm/mir/constant.rs
+++ b/src/librustc_codegen_llvm/mir/constant.rs
@@ -9,12 +9,11 @@
 // except according to those terms.
 
 use llvm;
-use rustc::mir::interpret::{ConstEvalErr, read_target_uint};
+use rustc::mir::interpret::{ErrorHandled, read_target_uint};
 use rustc_mir::const_eval::const_field;
 use rustc::hir::def_id::DefId;
 use rustc::mir;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_data_structures::sync::Lrc;
 use rustc::mir::interpret::{GlobalId, Pointer, Scalar, Allocation, ConstValue, AllocType};
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, HasDataLayout, LayoutOf, Size};
@@ -88,8 +87,8 @@ pub fn scalar_to_llvm(
 
 pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
     let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1);
-    let layout = cx.data_layout();
-    let pointer_size = layout.pointer_size.bytes() as usize;
+    let dl = cx.data_layout();
+    let pointer_size = dl.pointer_size.bytes() as usize;
 
     let mut next_offset = 0;
     for &(offset, ((), alloc_id)) in alloc.relocations.iter() {
@@ -100,7 +99,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
             llvals.push(C_bytes(cx, &alloc.bytes[next_offset..offset]));
         }
         let ptr_offset = read_target_uint(
-            layout.endian,
+            dl.endian,
             &alloc.bytes[offset..(offset + pointer_size)],
         ).expect("const_alloc_to_llvm: could not read relocation pointer") as u64;
         llvals.push(scalar_to_llvm(
@@ -124,7 +123,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
 pub fn codegen_static_initializer(
     cx: &CodegenCx<'ll, 'tcx>,
     def_id: DefId,
-) -> Result<(&'ll Value, &'tcx Allocation), Lrc<ConstEvalErr<'tcx>>> {
+) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
     let instance = ty::Instance::mono(cx.tcx, def_id);
     let cid = GlobalId {
         instance,
@@ -145,7 +144,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
         &mut self,
         bx: &Builder<'a, 'll, 'tcx>,
         constant: &'tcx ty::Const<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
+    ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> {
         match constant.val {
             ConstValue::Unevaluated(def_id, ref substs) => {
                 let tcx = bx.tcx();
@@ -165,7 +164,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
         &mut self,
         bx: &Builder<'a, 'll, 'tcx>,
         constant: &mir::Constant<'tcx>,
-    ) -> Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
+    ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> {
         let c = self.monomorphize(&constant.literal);
         self.fully_evaluate(bx, c)
     }
@@ -176,7 +175,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
         bx: &Builder<'a, 'll, 'tcx>,
         span: Span,
         ty: Ty<'tcx>,
-        constant: Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>>,
+        constant: Result<&'tcx ty::Const<'tcx>, ErrorHandled>,
     ) -> (&'ll Value, Ty<'tcx>) {
         constant
             .and_then(|c| {
@@ -185,7 +184,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
                     ty::Array(_, n) => n.unwrap_usize(bx.tcx()),
                     ref other => bug!("invalid simd shuffle type: {}", other),
                 };
-                let values: Result<Vec<_>, Lrc<_>> = (0..fields).map(|field| {
+                let values: Result<Vec<_>, ErrorHandled> = (0..fields).map(|field| {
                     let field = const_field(
                         bx.tcx(),
                         ty::ParamEnv::reveal_all(),
@@ -211,9 +210,9 @@ impl FunctionCx<'a, 'll, 'tcx> {
                 let llval = C_struct(bx.cx, &values?, false);
                 Ok((llval, c.ty))
             })
-            .unwrap_or_else(|e| {
-                e.report_as_error(
-                    bx.tcx().at(span),
+            .unwrap_or_else(|_| {
+                bx.tcx().sess.span_err(
+                    span,
                     "could not evaluate shuffle_indices at compile time",
                 );
                 // We've errored, so we don't have to produce working code.
diff --git a/src/librustc_codegen_llvm/mir/mod.rs b/src/librustc_codegen_llvm/mir/mod.rs
index a6e2ccf92e4..e5b25ea068b 100644
--- a/src/librustc_codegen_llvm/mir/mod.rs
+++ b/src/librustc_codegen_llvm/mir/mod.rs
@@ -12,6 +12,7 @@ use common::{C_i32, C_null};
 use libc::c_uint;
 use llvm::{self, BasicBlock};
 use llvm::debuginfo::DIScope;
+use llvm_util;
 use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
 use rustc::ty::layout::{LayoutOf, TyLayout};
 use rustc::mir::{self, Mir};
@@ -612,7 +613,7 @@ fn arg_local_refs(
             // doesn't actually strip the offset when splitting the closure
             // environment into its components so it ends up out of bounds.
             // (cuviper) It seems to be fine without the alloca on LLVM 6 and later.
-            let env_alloca = !env_ref && unsafe { llvm::LLVMRustVersionMajor() < 6 };
+            let env_alloca = !env_ref && llvm_util::get_major_version() < 6;
             let env_ptr = if env_alloca {
                 let scratch = PlaceRef::alloca(bx,
                     bx.cx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
diff --git a/src/librustc_codegen_llvm/mir/operand.rs b/src/librustc_codegen_llvm/mir/operand.rs
index ab43531240f..c76cbfcd971 100644
--- a/src/librustc_codegen_llvm/mir/operand.rs
+++ b/src/librustc_codegen_llvm/mir/operand.rs
@@ -8,11 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::mir::interpret::{ConstValue, ConstEvalErr};
+use rustc::mir::interpret::{ConstValue, ErrorHandled};
 use rustc::mir;
 use rustc::ty;
 use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
-use rustc_data_structures::sync::Lrc;
 
 use base;
 use common::{CodegenCx, C_undef, C_usize};
@@ -79,7 +78,7 @@ impl OperandRef<'ll, 'tcx> {
 
     pub fn from_const(bx: &Builder<'a, 'll, 'tcx>,
                       val: &'tcx ty::Const<'tcx>)
-                      -> Result<OperandRef<'ll, 'tcx>, Lrc<ConstEvalErr<'tcx>>> {
+                      -> Result<OperandRef<'ll, 'tcx>, ErrorHandled> {
         let layout = bx.cx.layout_of(val.ty);
 
         if layout.is_zst() {
@@ -283,8 +282,8 @@ impl OperandValue<'ll> {
         }
         match self {
             OperandValue::Ref(r, None, source_align) => {
-                base::memcpy_ty(bx, dest.llval, r, dest.layout,
-                                source_align.min(dest.align), flags)
+                base::memcpy_ty(bx, dest.llval, dest.align, r, source_align,
+                                dest.layout, flags)
             }
             OperandValue::Ref(_, Some(_), _) => {
                 bug!("cannot directly store unsized values");
@@ -325,7 +324,7 @@ impl OperandValue<'ll> {
         // Allocate an appropriate region on the stack, and copy the value into it
         let (llsize, _) = glue::size_and_align_of_dst(&bx, unsized_ty, Some(llextra));
         let lldst = bx.array_alloca(Type::i8(bx.cx), llsize, "unsized_tmp", max_align);
-        base::call_memcpy(&bx, lldst, llptr, llsize, min_align, flags);
+        base::call_memcpy(&bx, lldst, max_align, llptr, min_align, llsize, flags);
 
         // Store the allocated region and the extra to the indirect place.
         let indirect_operand = OperandValue::Pair(lldst, llextra);
@@ -424,10 +423,13 @@ impl FunctionCx<'a, 'll, 'tcx> {
                 self.eval_mir_constant(bx, constant)
                     .and_then(|c| OperandRef::from_const(bx, c))
                     .unwrap_or_else(|err| {
-                        err.report_as_error(
-                            bx.tcx().at(constant.span),
-                            "could not evaluate constant operand",
-                        );
+                        match err {
+                            // errored or at least linted
+                            ErrorHandled::Reported => {},
+                            ErrorHandled::TooGeneric => {
+                                bug!("codgen encountered polymorphic constant")
+                            },
+                        }
                         // Allow RalfJ to sleep soundly knowing that even refactorings that remove
                         // the above error (or silence it under some conditions) will not cause UB
                         let fnname = bx.cx.get_intrinsic(&("llvm.trap"));
diff --git a/src/librustc_codegen_llvm/mir/place.rs b/src/librustc_codegen_llvm/mir/place.rs
index e7b6f5908a4..75ec5ead243 100644
--- a/src/librustc_codegen_llvm/mir/place.rs
+++ b/src/librustc_codegen_llvm/mir/place.rs
@@ -10,7 +10,7 @@
 
 use llvm::{self, LLVMConstInBoundsGEP};
 use rustc::ty::{self, Ty};
-use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size};
+use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size, VariantIdx};
 use rustc::mir;
 use rustc::mir::tcx::PlaceTy;
 use base;
@@ -281,7 +281,7 @@ impl PlaceRef<'ll, 'tcx> {
         match self.layout.variants {
             layout::Variants::Single { index } => {
                 let discr_val = self.layout.ty.ty_adt_def().map_or(
-                    index as u128,
+                    index.as_u32() as u128,
                     |def| def.discriminant_for_variant(bx.cx.tcx, index).val);
                 return C_uint_big(cast_to, discr_val);
             }
@@ -320,16 +320,16 @@ impl PlaceRef<'ll, 'tcx> {
                         C_uint_big(niche_llty, niche_start)
                     };
                     bx.select(bx.icmp(llvm::IntEQ, lldiscr, niche_llval),
-                        C_uint(cast_to, *niche_variants.start() as u64),
-                        C_uint(cast_to, dataful_variant as u64))
+                        C_uint(cast_to, niche_variants.start().as_u32() as u64),
+                        C_uint(cast_to, dataful_variant.as_u32() as u64))
                 } else {
                     // Rebase from niche values to discriminant values.
-                    let delta = niche_start.wrapping_sub(*niche_variants.start() as u128);
+                    let delta = niche_start.wrapping_sub(niche_variants.start().as_u32() as u128);
                     let lldiscr = bx.sub(lldiscr, C_uint_big(niche_llty, delta));
-                    let lldiscr_max = C_uint(niche_llty, *niche_variants.end() as u64);
+                    let lldiscr_max = C_uint(niche_llty, niche_variants.end().as_u32() as u64);
                     bx.select(bx.icmp(llvm::IntULE, lldiscr, lldiscr_max),
                         bx.intcast(lldiscr, cast_to, false),
-                        C_uint(cast_to, dataful_variant as u64))
+                        C_uint(cast_to, dataful_variant.as_u32() as u64))
                 }
             }
         }
@@ -337,7 +337,7 @@ impl PlaceRef<'ll, 'tcx> {
 
     /// Set the discriminant for a new value of the given case of the given
     /// representation.
-    pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize) {
+    pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: VariantIdx) {
         if self.layout.for_variant(bx.cx, variant_index).abi.is_uninhabited() {
             return;
         }
@@ -376,7 +376,8 @@ impl PlaceRef<'ll, 'tcx> {
 
                     let niche = self.project_field(bx, 0);
                     let niche_llty = niche.layout.immediate_llvm_type(bx.cx);
-                    let niche_value = ((variant_index - *niche_variants.start()) as u128)
+                    let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
+                    let niche_value = (niche_value as u128)
                         .wrapping_add(niche_start);
                     // FIXME(eddyb) Check the actual primitive type here.
                     let niche_llval = if niche_value == 0 {
@@ -401,7 +402,7 @@ impl PlaceRef<'ll, 'tcx> {
         }
     }
 
-    pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize)
+    pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: VariantIdx)
                             -> PlaceRef<'ll, 'tcx> {
         let mut downcast = *self;
         downcast.layout = self.layout.for_variant(bx.cx, variant_index);
@@ -517,7 +518,8 @@ impl FunctionCx<'a, 'll, 'tcx> {
                         let mut subslice = cg_base.project_index(bx,
                             C_usize(bx.cx, from as u64));
                         let projected_ty = PlaceTy::Ty { ty: cg_base.layout.ty }
-                            .projection_ty(tcx, &projection.elem).to_ty(bx.tcx());
+                            .projection_ty(tcx, &projection.elem)
+                            .to_ty(bx.tcx());
                         subslice.layout = bx.cx.layout_of(self.monomorphize(&projected_ty));
 
                         if subslice.layout.is_unsized() {
diff --git a/src/librustc_codegen_llvm/mir/statement.rs b/src/librustc_codegen_llvm/mir/statement.rs
index 93be0074f6e..8bda2c98594 100644
--- a/src/librustc_codegen_llvm/mir/statement.rs
+++ b/src/librustc_codegen_llvm/mir/statement.rs
@@ -84,21 +84,18 @@ impl FunctionCx<'a, 'll, 'tcx> {
                 }).collect();
 
                 let input_vals = inputs.iter()
-                    .try_fold(Vec::with_capacity(inputs.len()), |mut acc, input| {
+                    .fold(Vec::with_capacity(inputs.len()), |mut acc, (span, input)| {
                         let op = self.codegen_operand(&bx, input);
                         if let OperandValue::Immediate(_) = op.val {
                             acc.push(op.immediate());
-                            Ok(acc)
                         } else {
-                            Err(op)
+                            span_err!(bx.sess(), span.to_owned(), E0669,
+                                     "invalid value for constraint in inline assembly");
                         }
+                        acc
                 });
 
-                if input_vals.is_err() {
-                   span_err!(bx.sess(), statement.source_info.span, E0669,
-                             "invalid value for constraint in inline assembly");
-                } else {
-                    let input_vals = input_vals.unwrap();
+                if input_vals.len() == inputs.len() {
                     let res = asm::codegen_inline_asm(&bx, asm, outputs, input_vals);
                     if !res {
                         span_err!(bx.sess(), statement.source_info.span, E0668,
@@ -108,8 +105,9 @@ impl FunctionCx<'a, 'll, 'tcx> {
                 bx
             }
             mir::StatementKind::FakeRead(..) |
-            mir::StatementKind::EndRegion(_) |
-            mir::StatementKind::Validate(..) |
+            mir::StatementKind::EndRegion(..) |
+            mir::StatementKind::Retag { .. } |
+            mir::StatementKind::EscapeToRaw { .. } |
             mir::StatementKind::AscribeUserType(..) |
             mir::StatementKind::Nop => bx,
         }