1- use std:: collections:: HashSet ;
21use std:: fmt:: Write ;
32
43use rustc:: hir:: def_id:: DefId ;
4+ use rustc:: hir:: def:: Def ;
55use rustc:: hir:: map:: definitions:: DefPathData ;
66use rustc:: middle:: const_val:: { ConstVal , ErrKind } ;
77use rustc:: mir;
88use rustc:: ty:: layout:: { self , Size , Align , HasDataLayout , LayoutOf , TyLayout } ;
99use rustc:: ty:: subst:: { Subst , Substs } ;
1010use rustc:: ty:: { self , Ty , TyCtxt } ;
1111use rustc:: ty:: maps:: TyCtxtAt ;
12- use rustc_data_structures:: indexed_vec:: Idx ;
12+ use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
1313use rustc:: middle:: const_val:: FrameInfo ;
1414use syntax:: codemap:: { self , Span } ;
1515use syntax:: ast:: Mutability ;
1616use rustc:: mir:: interpret:: {
1717 GlobalId , Value , Pointer , PrimVal , PrimValKind ,
1818 EvalError , EvalResult , EvalErrorKind , MemoryPointer ,
1919} ;
20+ use std:: mem;
2021
2122use super :: { Place , PlaceExtra , Memory ,
2223 HasMemory , MemoryKind ,
@@ -71,12 +72,12 @@ pub struct Frame<'mir, 'tcx: 'mir> {
7172 pub return_place : Place ,
7273
7374 /// The list of locals for this stack frame, stored in order as
74- /// `[arguments..., variables..., temporaries...]`. The locals are stored as `Option<Value>`s.
75+ /// `[return_ptr, arguments..., variables..., temporaries...]`. The locals are stored as `Option<Value>`s.
7576 /// `None` represents a local that is currently dead, while a live local
7677 /// can either directly contain `PrimVal` or refer to some part of an `Allocation`.
7778 ///
7879 /// Before being initialized, arguments are `Value::ByVal(PrimVal::Undef)` and other locals are `None`.
79- pub locals : Vec < Option < Value > > ,
80+ pub locals : IndexVec < mir :: Local , Option < Value > > ,
8081
8182 ////////////////////////////////////////////////////////////////////////////////
8283 // Current position within the function
@@ -383,39 +384,29 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
383384 ) -> EvalResult < ' tcx > {
384385 :: log_settings:: settings ( ) . indentation += 1 ;
385386
386- /// Return the set of locals that have a storage annotation anywhere
387- fn collect_storage_annotations < ' mir , ' tcx > ( mir : & ' mir mir:: Mir < ' tcx > ) -> HashSet < mir:: Local > {
388- use rustc:: mir:: StatementKind :: * ;
389-
390- let mut set = HashSet :: new ( ) ;
391- for block in mir. basic_blocks ( ) {
392- for stmt in block. statements . iter ( ) {
393- match stmt. kind {
394- StorageLive ( local) |
395- StorageDead ( local) => {
396- set. insert ( local) ;
387+ let locals = if mir. local_decls . len ( ) > 1 {
388+ let mut locals = IndexVec :: from_elem ( Some ( Value :: ByVal ( PrimVal :: Undef ) ) , & mir. local_decls ) ;
389+ match self . tcx . describe_def ( instance. def_id ( ) ) {
390+ // statics and constants don't have `Storage*` statements, no need to look for them
391+ Some ( Def :: Static ( ..) ) | Some ( Def :: Const ( ..) ) | Some ( Def :: AssociatedConst ( ..) ) => { } ,
392+ _ => {
393+ trace ! ( "push_stack_frame: {:?}: num_bbs: {}" , span, mir. basic_blocks( ) . len( ) ) ;
394+ for block in mir. basic_blocks ( ) {
395+ for stmt in block. statements . iter ( ) {
396+ use rustc:: mir:: StatementKind :: { StorageDead , StorageLive } ;
397+ match stmt. kind {
398+ StorageLive ( local) |
399+ StorageDead ( local) => locals[ local] = None ,
400+ _ => { }
401+ }
397402 }
398- _ => { }
399403 }
400- }
401- }
402- set
403- }
404-
405- // Subtract 1 because `local_decls` includes the ReturnMemoryPointer, but we don't store a local
406- // `Value` for that.
407- let num_locals = mir. local_decls . len ( ) - 1 ;
408-
409- let locals = {
410- let annotated_locals = collect_storage_annotations ( mir) ;
411- let mut locals = vec ! [ None ; num_locals] ;
412- for i in 0 ..num_locals {
413- let local = mir:: Local :: new ( i + 1 ) ;
414- if !annotated_locals. contains ( & local) {
415- locals[ i] = Some ( Value :: ByVal ( PrimVal :: Undef ) ) ;
416- }
404+ } ,
417405 }
418406 locals
407+ } else {
408+ // don't allocate at all for trivial constants
409+ IndexVec :: new ( )
419410 } ;
420411
421412 self . stack . push ( Frame {
@@ -973,8 +964,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
973964 pub fn force_allocation ( & mut self , place : Place ) -> EvalResult < ' tcx , Place > {
974965 let new_place = match place {
975966 Place :: Local { frame, local } => {
976- // -1 since we don't store the return value
977- match self . stack [ frame] . locals [ local. index ( ) - 1 ] {
967+ match self . stack [ frame] . locals [ local] {
978968 None => return err ! ( DeadLocal ) ,
979969 Some ( Value :: ByRef ( ptr, align) ) => {
980970 Place :: Ptr {
@@ -988,7 +978,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
988978 let ty = self . monomorphize ( ty, self . stack [ frame] . instance . substs ) ;
989979 let layout = self . layout_of ( ty) ?;
990980 let ptr = self . alloc_ptr ( ty) ?;
991- self . stack [ frame] . locals [ local. index ( ) - 1 ] =
981+ self . stack [ frame] . locals [ local] =
992982 Some ( Value :: ByRef ( ptr. into ( ) , layout. align ) ) ; // it stays live
993983 let place = Place :: from_ptr ( ptr, layout. align ) ;
994984 self . write_value ( ValTy { value : val, ty } , place) ?;
@@ -1702,13 +1692,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
17021692
17031693impl < ' mir , ' tcx > Frame < ' mir , ' tcx > {
17041694 pub fn get_local ( & self , local : mir:: Local ) -> EvalResult < ' tcx , Value > {
1705- // Subtract 1 because we don't store a value for the ReturnPointer, the local with index 0.
1706- self . locals [ local. index ( ) - 1 ] . ok_or ( EvalErrorKind :: DeadLocal . into ( ) )
1695+ self . locals [ local] . ok_or ( EvalErrorKind :: DeadLocal . into ( ) )
17071696 }
17081697
17091698 fn set_local ( & mut self , local : mir:: Local , value : Value ) -> EvalResult < ' tcx > {
1710- // Subtract 1 because we don't store a value for the ReturnPointer, the local with index 0.
1711- match self . locals [ local. index ( ) - 1 ] {
1699+ match self . locals [ local] {
17121700 None => err ! ( DeadLocal ) ,
17131701 Some ( ref mut local) => {
17141702 * local = value;
@@ -1717,20 +1705,17 @@ impl<'mir, 'tcx> Frame<'mir, 'tcx> {
17171705 }
17181706 }
17191707
1720- pub fn storage_live ( & mut self , local : mir:: Local ) -> EvalResult < ' tcx , Option < Value > > {
1708+ pub fn storage_live ( & mut self , local : mir:: Local ) -> Option < Value > {
17211709 trace ! ( "{:?} is now live" , local) ;
17221710
1723- let old = self . locals [ local. index ( ) - 1 ] ;
1724- self . locals [ local. index ( ) - 1 ] = Some ( Value :: ByVal ( PrimVal :: Undef ) ) ; // StorageLive *always* kills the value that's currently stored
1725- return Ok ( old) ;
1711+ // StorageLive *always* kills the value that's currently stored
1712+ mem:: replace ( & mut self . locals [ local] , Some ( Value :: ByVal ( PrimVal :: Undef ) ) )
17261713 }
17271714
17281715 /// Returns the old value of the local
1729- pub fn storage_dead ( & mut self , local : mir:: Local ) -> EvalResult < ' tcx , Option < Value > > {
1716+ pub fn storage_dead ( & mut self , local : mir:: Local ) -> Option < Value > {
17301717 trace ! ( "{:?} is now dead" , local) ;
17311718
1732- let old = self . locals [ local. index ( ) - 1 ] ;
1733- self . locals [ local. index ( ) - 1 ] = None ;
1734- return Ok ( old) ;
1719+ self . locals [ local] . take ( )
17351720 }
17361721}
0 commit comments