@@ -73,23 +73,13 @@ pub struct Frame<'a, 'tcx: 'a> {
73
73
// Return pointer and local allocations
74
74
////////////////////////////////////////////////////////////////////////////////
75
75
76
- /// A pointer for writing the return value of the current call if it's not a diverging call.
77
- pub return_ptr : Option < Pointer > ,
78
-
79
76
/// The block to return to when returning from the current stack frame
80
77
pub return_to_block : StackPopCleanup ,
81
78
82
79
/// The list of locals for the current function, stored in order as
83
- /// `[arguments..., variables..., temporaries...]`. The variables begin at `self.var_offset`
84
- /// and the temporaries at `self.temp_offset`.
80
+ /// `[return_ptr, arguments..., variables..., temporaries...]`.
85
81
pub locals : Vec < Pointer > ,
86
82
87
- /// The offset of the first variable in `self.locals`.
88
- pub var_offset : usize ,
89
-
90
- /// The offset of the first temporary in `self.locals`.
91
- pub temp_offset : usize ,
92
-
93
83
////////////////////////////////////////////////////////////////////////////////
94
84
// Current position within the function
95
85
////////////////////////////////////////////////////////////////////////////////
@@ -336,32 +326,26 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
336
326
span : codemap:: Span ,
337
327
mir : CachedMir < ' a , ' tcx > ,
338
328
substs : & ' tcx Substs < ' tcx > ,
339
- return_ptr : Option < Pointer > ,
329
+ return_ptr : Pointer ,
340
330
return_to_block : StackPopCleanup ,
341
331
) -> EvalResult < ' tcx , ( ) > {
342
- let arg_tys = mir. arg_decls . iter ( ) . map ( |a| a. ty ) ;
343
- let var_tys = mir. var_decls . iter ( ) . map ( |v| v. ty ) ;
344
- let temp_tys = mir. temp_decls . iter ( ) . map ( |t| t. ty ) ;
345
-
346
- let num_args = mir. arg_decls . len ( ) ;
347
- let num_vars = mir. var_decls . len ( ) ;
332
+ let local_tys = mir. local_decls . iter ( ) . map ( |a| a. ty ) ;
348
333
349
334
:: log_settings:: settings ( ) . indentation += 1 ;
350
335
351
- let locals: EvalResult < ' tcx , Vec < Pointer > > = arg_tys. chain ( var_tys) . chain ( temp_tys) . map ( |ty| {
336
+ // directly change the first allocation (the return value) to *be* the allocation where the
337
+ // caller stores the result
338
+ let locals: EvalResult < ' tcx , Vec < Pointer > > = iter:: once ( Ok ( return_ptr) ) . chain ( local_tys. skip ( 1 ) . map ( |ty| {
352
339
let size = self . type_size_with_substs ( ty, substs) ;
353
340
let align = self . type_align_with_substs ( ty, substs) ;
354
341
self . memory . allocate ( size, align)
355
- } ) . collect ( ) ;
342
+ } ) ) . collect ( ) ;
356
343
357
344
self . stack . push ( Frame {
358
345
mir : mir. clone ( ) ,
359
346
block : mir:: START_BLOCK ,
360
- return_ptr : return_ptr,
361
347
return_to_block : return_to_block,
362
348
locals : locals?,
363
- var_offset : num_args,
364
- temp_offset : num_args + num_vars,
365
349
span : span,
366
350
def_id : def_id,
367
351
substs : substs,
@@ -793,11 +777,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
793
777
fn eval_lvalue ( & mut self , lvalue : & mir:: Lvalue < ' tcx > ) -> EvalResult < ' tcx , Lvalue > {
794
778
use rustc:: mir:: repr:: Lvalue :: * ;
795
779
let ptr = match * lvalue {
796
- ReturnPointer => self . frame ( ) . return_ptr
797
- . expect ( "ReturnPointer used in a function with no return value" ) ,
798
- Arg ( i) => self . frame ( ) . locals [ i. index ( ) ] ,
799
- Var ( i) => self . frame ( ) . locals [ self . frame ( ) . var_offset + i. index ( ) ] ,
800
- Temp ( i) => self . frame ( ) . locals [ self . frame ( ) . temp_offset + i. index ( ) ] ,
780
+ Local ( i) => self . frame ( ) . locals [ i. index ( ) ] ,
801
781
802
782
Static ( def_id) => {
803
783
let substs = subst:: Substs :: empty ( self . tcx ) ;
@@ -819,11 +799,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
819
799
Field ( field, field_ty) => {
820
800
let field_ty = self . monomorphize ( field_ty, self . substs ( ) ) ;
821
801
use rustc:: ty:: layout:: Layout :: * ;
822
- let variant = match * base_layout {
823
- Univariant { ref variant, .. } => variant,
802
+ let field = field. index ( ) ;
803
+ let offset = match * base_layout {
804
+ Univariant { ref variant, .. } => variant. field_offset ( field) ,
824
805
General { ref variants, .. } => {
825
806
if let LvalueExtra :: DowncastVariant ( variant_idx) = base. extra {
826
- & variants[ variant_idx]
807
+ // +1 for the discriminant, which is field 0
808
+ variants[ variant_idx] . field_offset ( field + 1 )
827
809
} else {
828
810
bug ! ( "field access on enum had no variant index" ) ;
829
811
}
@@ -832,14 +814,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
832
814
assert_eq ! ( field. index( ) , 0 ) ;
833
815
return Ok ( base) ;
834
816
}
835
- StructWrappedNullablePointer { ref nonnull, .. } => nonnull,
817
+ StructWrappedNullablePointer { ref nonnull, .. } => nonnull. field_offset ( field ) ,
836
818
_ => bug ! ( "field access on non-product type: {:?}" , base_layout) ,
837
819
} ;
838
820
839
- let offset = variant. field_offset ( field. index ( ) ) . bytes ( ) ;
840
- let ptr = base. ptr . offset ( offset as isize ) ;
841
- trace ! ( "{:?}" , base) ;
842
- trace ! ( "{:?}" , field_ty) ;
821
+ let ptr = base. ptr . offset ( offset. bytes ( ) as isize ) ;
843
822
if self . type_is_sized ( field_ty) {
844
823
ptr
845
824
} else {
@@ -859,9 +838,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
859
838
Downcast ( _, variant) => {
860
839
use rustc:: ty:: layout:: Layout :: * ;
861
840
match * base_layout {
862
- General { ref variants , .. } => {
841
+ General { .. } => {
863
842
return Ok ( Lvalue {
864
- ptr : base. ptr . offset ( variants [ variant ] . field_offset ( 1 ) . bytes ( ) as isize ) ,
843
+ ptr : base. ptr ,
865
844
extra : LvalueExtra :: DowncastVariant ( variant) ,
866
845
} ) ;
867
846
}
@@ -1220,18 +1199,17 @@ pub fn eval_main<'a, 'tcx: 'a>(
1220
1199
let return_ptr = ecx. alloc_ret_ptr ( mir. return_ty , substs)
1221
1200
. expect ( "should at least be able to allocate space for the main function's return value" ) ;
1222
1201
1223
- ecx. push_stack_frame ( def_id, mir. span , CachedMir :: Ref ( mir) , substs, Some ( return_ptr) , StackPopCleanup :: None )
1202
+ ecx. push_stack_frame ( def_id, mir. span , CachedMir :: Ref ( mir) , substs, return_ptr, StackPopCleanup :: None )
1224
1203
. expect ( "could not allocate first stack frame" ) ;
1225
1204
1226
- if mir. arg_decls . len ( ) == 2 {
1205
+ // FIXME: this is a horrible and wrong way to detect the start function, but overwriting the first two locals shouldn't do much
1206
+ if mir. local_decls . len ( ) > 2 {
1227
1207
// start function
1228
- let ptr_size = ecx. memory ( ) . pointer_size ( ) ;
1229
- let nargs = ecx. memory_mut ( ) . allocate ( ptr_size, ptr_size) . expect ( "can't allocate memory for nargs" ) ;
1230
- ecx. memory_mut ( ) . write_usize ( nargs, 0 ) . unwrap ( ) ;
1231
- let args = ecx. memory_mut ( ) . allocate ( ptr_size, ptr_size) . expect ( "can't allocate memory for arg pointer" ) ;
1232
- ecx. memory_mut ( ) . write_usize ( args, 0 ) . unwrap ( ) ;
1233
- ecx. frame_mut ( ) . locals [ 0 ] = nargs;
1234
- ecx. frame_mut ( ) . locals [ 1 ] = args;
1208
+ let nargs = ecx. frame_mut ( ) . locals [ 1 ] ;
1209
+ let args = ecx. frame_mut ( ) . locals [ 2 ] ;
1210
+ // ignore errors, if the locals are too small this is not the start function
1211
+ let _ = ecx. memory_mut ( ) . write_usize ( nargs, 0 ) ;
1212
+ let _ = ecx. memory_mut ( ) . write_usize ( args, 0 ) ;
1235
1213
}
1236
1214
1237
1215
for _ in 0 ..step_limit {
0 commit comments