diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index ae4ad49fe667f..02fce7dfb43c2 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -81,14 +81,9 @@ pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> {
     ////////////////////////////////////////////////////////////////////////////////
     // Current position within the function
     ////////////////////////////////////////////////////////////////////////////////
-    /// The block that is currently executed (or will be executed after the above call stacks
-    /// return).
     /// If this is `None`, we are unwinding and this function doesn't need any clean-up.
     /// Just continue the same as with `Resume`.
-    pub block: Option<mir::BasicBlock>,
-
-    /// The index of the currently evaluated statement.
-    pub stmt: usize,
+    pub loc: Option<mir::Location>,
 }
 
 #[derive(Clone, Eq, PartialEq, Debug, HashStable)] // Miri debug-prints these
@@ -168,8 +163,7 @@ impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> {
             return_to_block: self.return_to_block,
             return_place: self.return_place,
             locals: self.locals,
-            block: self.block,
-            stmt: self.stmt,
+            loc: self.loc,
             extra,
         }
     }
@@ -178,10 +172,10 @@ impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> {
 impl<'mir, 'tcx, Tag, Extra> Frame<'mir, 'tcx, Tag, Extra> {
     /// Return the `SourceInfo` of the current instruction.
     pub fn current_source_info(&self) -> Option<mir::SourceInfo> {
-        self.block.map(|block| {
-            let block = &self.body.basic_blocks()[block];
-            if self.stmt < block.statements.len() {
-                block.statements[self.stmt].source_info
+        self.loc.map(|loc| {
+            let block = &self.body.basic_blocks()[loc.block];
+            if loc.statement_index < block.statements.len() {
+                block.statements[loc.statement_index].source_info
             } else {
                 block.terminator().source_info
             }
@@ -615,14 +609,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // first push a stack frame so we have access to the local substs
         let pre_frame = Frame {
             body,
-            block: Some(mir::START_BLOCK),
+            loc: Some(mir::Location::START),
             return_to_block,
             return_place,
             // empty local array, we fill it in below, after we are inside the stack frame and
             // all methods actually know about the frame
             locals: IndexVec::new(),
             instance,
-            stmt: 0,
             extra: (),
         };
         let frame = M::init_frame_extra(self, pre_frame)?;
@@ -671,9 +664,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Jump to the given block.
     #[inline]
     pub fn go_to_block(&mut self, target: mir::BasicBlock) {
-        let frame = self.frame_mut();
-        frame.block = Some(target);
-        frame.stmt = 0;
+        self.frame_mut().loc = Some(mir::Location { block: target, statement_index: 0 });
     }
 
     /// *Return* to the given `target` basic block.
@@ -695,9 +686,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// If `target` is `None`, that indicates the function does not need cleanup during
     /// unwinding, and we will just keep propagating that upwards.
     pub fn unwind_to_block(&mut self, target: Option<mir::BasicBlock>) {
-        let frame = self.frame_mut();
-        frame.block = target;
-        frame.stmt = 0;
+        self.frame_mut().loc = target.map(|block| mir::Location { block, statement_index: 0 });
     }
 
     /// Pops the current frame from the stack, deallocating the
@@ -724,9 +713,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // Sanity check `unwinding`.
         assert_eq!(
             unwinding,
-            match self.frame().block {
+            match self.frame().loc {
                 None => true,
-                Some(block) => self.body().basic_blocks()[block].is_cleanup,
+                Some(loc) => self.body().basic_blocks()[loc.block].is_cleanup,
             }
         );
 
@@ -987,13 +976,14 @@ where
     Tag: HashStable<StableHashingContext<'ctx>>,
 {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'ctx>, hasher: &mut StableHasher) {
-        self.body.hash_stable(hcx, hasher);
-        self.instance.hash_stable(hcx, hasher);
-        self.return_to_block.hash_stable(hcx, hasher);
-        self.return_place.as_ref().map(|r| &**r).hash_stable(hcx, hasher);
-        self.locals.hash_stable(hcx, hasher);
-        self.block.hash_stable(hcx, hasher);
-        self.stmt.hash_stable(hcx, hasher);
-        self.extra.hash_stable(hcx, hasher);
+        // Exhaustive match on fields to make sure we forget no field.
+        let Frame { body, instance, return_to_block, return_place, locals, loc, extra } = self;
+        body.hash_stable(hcx, hasher);
+        instance.hash_stable(hcx, hasher);
+        return_to_block.hash_stable(hcx, hasher);
+        return_place.as_ref().map(|r| &**r).hash_stable(hcx, hasher);
+        locals.hash_stable(hcx, hasher);
+        loc.hash_stable(hcx, hasher);
+        extra.hash_stable(hcx, hasher);
     }
 }
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index aae708827b953..bb4c0156c88cf 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -46,8 +46,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             return Ok(false);
         }
 
-        let block = match self.frame().block {
-            Some(block) => block,
+        let loc = match self.frame().loc {
+            Some(loc) => loc,
             None => {
                 // We are unwinding and this fn has no cleanup code.
                 // Just go on unwinding.
@@ -56,13 +56,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 return Ok(true);
             }
         };
-        let stmt_id = self.frame().stmt;
-        let body = self.body();
-        let basic_block = &body.basic_blocks()[block];
+        let basic_block = &self.body().basic_blocks()[loc.block];
 
         let old_frames = self.frame_idx();
 
-        if let Some(stmt) = basic_block.statements.get(stmt_id) {
+        if let Some(stmt) = basic_block.statements.get(loc.statement_index) {
             assert_eq!(old_frames, self.frame_idx());
             self.statement(stmt)?;
             return Ok(true);
@@ -126,7 +124,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             LlvmInlineAsm { .. } => throw_unsup_format!("inline assembly is not supported"),
         }
 
-        self.stack_mut()[frame_idx].stmt += 1;
+        self.stack_mut()[frame_idx].loc.as_mut().unwrap().statement_index += 1;
         Ok(())
     }
 
@@ -279,8 +277,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
         self.eval_terminator(terminator)?;
         if !self.stack().is_empty() {
-            if let Some(block) = self.frame().block {
-                info!("// executing {:?}", block);
+            if let Some(loc) = self.frame().loc {
+                info!("// executing {:?}", loc.block);
             }
         }
         Ok(())
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 7157225e5c9bb..6ead962dcd869 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -53,7 +53,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
             Call { ref func, ref args, destination, ref cleanup, .. } => {
                 let old_stack = self.frame_idx();
-                let old_bb = self.frame().block;
+                let old_loc = self.frame().loc;
                 let func = self.eval_operand(func, None)?;
                 let (fn_val, abi) = match func.layout.ty.kind {
                     ty::FnPtr(sig) => {
@@ -80,7 +80,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.eval_fn_call(fn_val, abi, &args[..], ret, *cleanup)?;
                 // Sanity-check that `eval_fn_call` either pushed a new frame or
                 // did a jump to another block.
-                if self.frame_idx() == old_stack && self.frame().block == old_bb {
+                if self.frame_idx() == old_stack && self.frame().loc == old_loc {
                     span_bug!(terminator.source_info.span, "evaluating this call made no progress");
                 }
             }