@@ -12,7 +12,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Binder};
12
12
use rustc:: traits;
13
13
use rustc_data_structures:: indexed_vec:: Idx ;
14
14
use syntax:: codemap:: { self , DUMMY_SP , Span } ;
15
- use syntax:: ast;
15
+ use syntax:: ast:: { self , Mutability } ;
16
16
use syntax:: abi:: Abi ;
17
17
18
18
use error:: { EvalError , EvalResult } ;
@@ -98,8 +98,7 @@ pub enum StackPopCleanup {
98
98
/// isn't modifyable afterwards in case of constants.
99
99
/// In case of `static mut`, mark the memory to ensure it's never marked as immutable through
100
100
/// references or deallocated
101
- /// The bool decides whether the value is mutable (true) or not (false)
102
- MarkStatic ( bool ) ,
101
+ MarkStatic ( Mutability ) ,
103
102
/// A regular stackframe added due to a function call will need to get forwarded to the next
104
103
/// block
105
104
Goto ( mir:: BasicBlock ) ,
@@ -154,7 +153,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
154
153
) -> EvalResult < ' tcx , MemoryPointer > {
155
154
let size = self . type_size_with_substs ( ty, substs) ?. expect ( "cannot alloc memory for unsized type" ) ;
156
155
let align = self . type_align_with_substs ( ty, substs) ?;
157
- self . memory . allocate ( size, align)
156
+ self . memory . allocate ( size, align, :: memory :: Kind :: Stack )
158
157
}
159
158
160
159
pub fn memory ( & self ) -> & Memory < ' a , ' tcx > {
@@ -370,7 +369,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
370
369
// see comment on `initialized` field
371
370
assert ! ( !global_value. initialized) ;
372
371
global_value. initialized = true ;
373
- assert ! ( global_value. mutable) ;
372
+ assert_eq ! ( global_value. mutable, Mutability :: Mutable ) ;
374
373
global_value. mutable = mutable;
375
374
} else {
376
375
bug ! ( "StackPopCleanup::MarkStatic on: {:?}" , frame. return_lvalue) ;
@@ -414,11 +413,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
414
413
trace ! ( "deallocating local" ) ;
415
414
let ptr = ptr. to_ptr ( ) ?;
416
415
self . memory . dump_alloc ( ptr. alloc_id ) ;
417
- match self . memory . deallocate ( ptr, None ) {
418
- // We could alternatively check whether the alloc_id is static before calling
419
- // deallocate, but this is much simpler and is probably the rare case.
420
- Ok ( ( ) ) | Err ( EvalError :: DeallocatedStaticMemory ) => { } ,
421
- other => return other,
416
+ match self . memory . get ( ptr. alloc_id ) ?. kind {
417
+ // for a constant like `const FOO: &i32 = &1;` the local containing
418
+ // the `1` is referred to by the global. We transitively marked everything
419
+ // the global refers to as static itself, so we don't free it here
420
+ :: memory:: Kind :: Static => { }
421
+ :: memory:: Kind :: Stack => self . memory . deallocate ( ptr, None , :: memory:: Kind :: Stack ) ?,
422
+ other => bug ! ( "local contained non-stack memory: {:?}" , other) ,
422
423
}
423
424
} ;
424
425
Ok ( ( ) )
@@ -693,11 +694,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
693
694
return Err ( EvalError :: NeedsRfc ( "\" heap\" allocations" . to_string ( ) ) ) ;
694
695
}
695
696
// FIXME: call the `exchange_malloc` lang item if available
696
- if self . type_size ( ty) ?. expect ( "box only works with sized types" ) == 0 {
697
+ let size = self . type_size ( ty) ?. expect ( "box only works with sized types" ) ;
698
+ if size == 0 {
697
699
let align = self . type_align ( ty) ?;
698
700
self . write_primval ( dest, PrimVal :: Bytes ( align. into ( ) ) , dest_ty) ?;
699
701
} else {
700
- let ptr = self . alloc_ptr ( ty) ?;
702
+ let align = self . type_align ( ty) ?;
703
+ let ptr = self . memory . allocate ( size, align, :: memory:: Kind :: Rust ) ?;
701
704
self . write_primval ( dest, PrimVal :: Ptr ( ptr) , dest_ty) ?;
702
705
}
703
706
}
@@ -1022,7 +1025,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1022
1025
}
1023
1026
Lvalue :: Ptr { .. } => lvalue,
1024
1027
Lvalue :: Global ( cid) => {
1025
- let global_val = * self . globals . get ( & cid) . expect ( "global not cached" ) ;
1028
+ let global_val = self . globals . get ( & cid) . expect ( "global not cached" ) . clone ( ) ;
1026
1029
match global_val. value {
1027
1030
Value :: ByRef ( ptr, aligned) =>
1028
1031
Lvalue :: Ptr { ptr, aligned, extra : LvalueExtra :: None } ,
@@ -1108,8 +1111,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1108
1111
1109
1112
match dest {
1110
1113
Lvalue :: Global ( cid) => {
1111
- let dest = * self . globals . get_mut ( & cid) . expect ( "global should be cached" ) ;
1112
- if ! dest. mutable {
1114
+ let dest = self . globals . get_mut ( & cid) . expect ( "global should be cached" ) . clone ( ) ;
1115
+ if dest. mutable == Mutability :: Immutable {
1113
1116
return Err ( EvalError :: ModifiedConstantMemory ) ;
1114
1117
}
1115
1118
let write_dest = |this : & mut Self , val| {
@@ -1594,8 +1597,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1594
1597
pub fn modify_global < F > ( & mut self , cid : GlobalId < ' tcx > , f : F ) -> EvalResult < ' tcx >
1595
1598
where F : FnOnce ( & mut Self , Value ) -> EvalResult < ' tcx , Value > ,
1596
1599
{
1597
- let mut val = * self . globals . get ( & cid) . expect ( "global not cached" ) ;
1598
- if ! val. mutable {
1600
+ let mut val = self . globals . get ( & cid) . expect ( "global not cached" ) . clone ( ) ;
1601
+ if val. mutable == Mutability :: Immutable {
1599
1602
return Err ( EvalError :: ModifiedConstantMemory ) ;
1600
1603
}
1601
1604
val. value = f ( self , val. value ) ?;
@@ -1686,7 +1689,7 @@ pub fn eval_main<'a, 'tcx: 'a>(
1686
1689
}
1687
1690
1688
1691
// Return value
1689
- let ret_ptr = ecx. memory . allocate ( ecx. tcx . data_layout . pointer_size . bytes ( ) , ecx. tcx . data_layout . pointer_align . abi ( ) ) ?;
1692
+ let ret_ptr = ecx. memory . allocate ( ecx. tcx . data_layout . pointer_size . bytes ( ) , ecx. tcx . data_layout . pointer_align . abi ( ) , :: memory :: Kind :: Stack ) ?;
1690
1693
cleanup_ptr = Some ( ret_ptr) ;
1691
1694
1692
1695
// Push our stack frame
@@ -1728,7 +1731,7 @@ pub fn eval_main<'a, 'tcx: 'a>(
1728
1731
1729
1732
while ecx. step ( ) ? { }
1730
1733
if let Some ( cleanup_ptr) = cleanup_ptr {
1731
- ecx. memory . deallocate ( cleanup_ptr, None ) ?;
1734
+ ecx. memory . deallocate ( cleanup_ptr, None , :: memory :: Kind :: Stack ) ?;
1732
1735
}
1733
1736
return Ok ( ( ) ) ;
1734
1737
}
0 commit comments