@@ -6,15 +6,15 @@ use rustc::traits::{self, ProjectionMode};
6
6
use rustc:: ty:: fold:: TypeFoldable ;
7
7
use rustc:: ty:: layout:: { self , Layout , Size } ;
8
8
use rustc:: ty:: subst:: { self , Subst , Substs } ;
9
- use rustc:: ty:: { self , Ty , TyCtxt } ;
9
+ use rustc:: ty:: { self , Ty , TyCtxt , BareFnTy } ;
10
10
use rustc:: util:: nodemap:: DefIdMap ;
11
11
use std:: cell:: RefCell ;
12
12
use std:: ops:: Deref ;
13
13
use std:: rc:: Rc ;
14
14
use std:: { iter, mem} ;
15
15
use syntax:: ast;
16
16
use syntax:: attr;
17
- use syntax:: codemap:: { self , DUMMY_SP } ;
17
+ use syntax:: codemap:: { self , DUMMY_SP , Span } ;
18
18
19
19
use error:: { EvalError , EvalResult } ;
20
20
use memory:: { Memory , Pointer } ;
@@ -39,7 +39,7 @@ pub struct EvalContext<'a, 'tcx: 'a> {
39
39
mir_cache : RefCell < DefIdMap < Rc < mir:: Mir < ' tcx > > > > ,
40
40
41
41
/// The virtual memory system.
42
- memory : Memory ,
42
+ memory : Memory < ' tcx > ,
43
43
44
44
/// Precomputed statics, constants and promoteds
45
45
statics : HashMap < ConstantId < ' tcx > , Pointer > ,
@@ -421,81 +421,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
421
421
422
422
let func_ty = self . operand_ty ( func) ;
423
423
match func_ty. sty {
424
+ ty:: TyFnPtr ( bare_fn_ty) => {
425
+ let ptr = self . eval_operand ( func) ?;
426
+ assert_eq ! ( ptr. offset, 0 ) ;
427
+ let fn_ptr = self . memory . read_ptr ( ptr) ?;
428
+ let ( def_id, substs) = self . memory . get_fn ( fn_ptr. alloc_id ) ?;
429
+ self . eval_fn_call ( def_id, substs, bare_fn_ty, return_ptr, args, terminator. span ) ?
430
+ } ,
424
431
ty:: TyFnDef ( def_id, substs, fn_ty) => {
425
- use syntax:: abi:: Abi ;
426
- match fn_ty. abi {
427
- Abi :: RustIntrinsic => {
428
- let name = self . tcx . item_name ( def_id) . as_str ( ) ;
429
- match fn_ty. sig . 0 . output {
430
- ty:: FnConverging ( ty) => {
431
- let size = self . type_size ( ty, self . substs ( ) ) ;
432
- let ret = return_ptr. unwrap ( ) ;
433
- self . call_intrinsic ( & name, substs, args, ret, size) ?
434
- }
435
- ty:: FnDiverging => unimplemented ! ( ) ,
436
- }
437
- }
438
-
439
- Abi :: C => {
440
- match fn_ty. sig . 0 . output {
441
- ty:: FnConverging ( ty) => {
442
- let size = self . type_size ( ty, self . substs ( ) ) ;
443
- self . call_c_abi ( def_id, args, return_ptr. unwrap ( ) , size) ?
444
- }
445
- ty:: FnDiverging => unimplemented ! ( ) ,
446
- }
447
- }
448
-
449
- Abi :: Rust | Abi :: RustCall => {
450
- // TODO(solson): Adjust the first argument when calling a Fn or
451
- // FnMut closure via FnOnce::call_once.
452
-
453
- // Only trait methods can have a Self parameter.
454
- let ( resolved_def_id, resolved_substs) = if substs. self_ty ( ) . is_some ( ) {
455
- self . trait_method ( def_id, substs)
456
- } else {
457
- ( def_id, substs)
458
- } ;
459
-
460
- let mut arg_srcs = Vec :: new ( ) ;
461
- for arg in args {
462
- let src = self . eval_operand ( arg) ?;
463
- let src_ty = self . operand_ty ( arg) ;
464
- arg_srcs. push ( ( src, src_ty) ) ;
465
- }
466
-
467
- if fn_ty. abi == Abi :: RustCall && !args. is_empty ( ) {
468
- arg_srcs. pop ( ) ;
469
- let last_arg = args. last ( ) . unwrap ( ) ;
470
- let last = self . eval_operand ( last_arg) ?;
471
- let last_ty = self . operand_ty ( last_arg) ;
472
- let last_layout = self . type_layout ( last_ty, self . substs ( ) ) ;
473
- match ( & last_ty. sty , last_layout) {
474
- ( & ty:: TyTuple ( fields) ,
475
- & Layout :: Univariant { ref variant, .. } ) => {
476
- let offsets = iter:: once ( 0 )
477
- . chain ( variant. offset_after_field . iter ( )
478
- . map ( |s| s. bytes ( ) ) ) ;
479
- for ( offset, ty) in offsets. zip ( fields) {
480
- let src = last. offset ( offset as isize ) ;
481
- arg_srcs. push ( ( src, ty) ) ;
482
- }
483
- }
484
- ty => panic ! ( "expected tuple as last argument in function with 'rust-call' ABI, got {:?}" , ty) ,
485
- }
486
- }
487
-
488
- let mir = self . load_mir ( resolved_def_id) ;
489
- self . push_stack_frame ( def_id, terminator. span , mir, resolved_substs, return_ptr) ;
490
-
491
- for ( i, ( src, src_ty) ) in arg_srcs. into_iter ( ) . enumerate ( ) {
492
- let dest = self . frame ( ) . locals [ i] ;
493
- self . move_ ( src, dest, src_ty) ?;
494
- }
495
- }
496
-
497
- abi => return Err ( EvalError :: Unimplemented ( format ! ( "can't handle function with {:?} ABI" , abi) ) ) ,
498
- }
432
+ self . eval_fn_call ( def_id, substs, fn_ty, return_ptr, args, terminator. span ) ?
499
433
}
500
434
501
435
_ => return Err ( EvalError :: Unimplemented ( format ! ( "can't handle callee of type {:?}" , func_ty) ) ) ,
@@ -515,6 +449,93 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
515
449
Ok ( ( ) )
516
450
}
517
451
452
+ pub fn eval_fn_call (
453
+ & mut self ,
454
+ def_id : DefId ,
455
+ substs : & ' tcx Substs < ' tcx > ,
456
+ fn_ty : & ' tcx BareFnTy ,
457
+ return_ptr : Option < Pointer > ,
458
+ args : & [ mir:: Operand < ' tcx > ] ,
459
+ span : Span ,
460
+ ) -> EvalResult < ( ) > {
461
+ use syntax:: abi:: Abi ;
462
+ match fn_ty. abi {
463
+ Abi :: RustIntrinsic => {
464
+ let name = self . tcx . item_name ( def_id) . as_str ( ) ;
465
+ match fn_ty. sig . 0 . output {
466
+ ty:: FnConverging ( ty) => {
467
+ let size = self . type_size ( ty, self . substs ( ) ) ;
468
+ let ret = return_ptr. unwrap ( ) ;
469
+ self . call_intrinsic ( & name, substs, args, ret, size)
470
+ }
471
+ ty:: FnDiverging => unimplemented ! ( ) ,
472
+ }
473
+ }
474
+
475
+ Abi :: C => {
476
+ match fn_ty. sig . 0 . output {
477
+ ty:: FnConverging ( ty) => {
478
+ let size = self . type_size ( ty, self . substs ( ) ) ;
479
+ self . call_c_abi ( def_id, args, return_ptr. unwrap ( ) , size)
480
+ }
481
+ ty:: FnDiverging => unimplemented ! ( ) ,
482
+ }
483
+ }
484
+
485
+ Abi :: Rust | Abi :: RustCall => {
486
+ // TODO(solson): Adjust the first argument when calling a Fn or
487
+ // FnMut closure via FnOnce::call_once.
488
+
489
+ // Only trait methods can have a Self parameter.
490
+ let ( resolved_def_id, resolved_substs) = if substs. self_ty ( ) . is_some ( ) {
491
+ self . trait_method ( def_id, substs)
492
+ } else {
493
+ ( def_id, substs)
494
+ } ;
495
+
496
+ let mut arg_srcs = Vec :: new ( ) ;
497
+ for arg in args {
498
+ let src = self . eval_operand ( arg) ?;
499
+ let src_ty = self . operand_ty ( arg) ;
500
+ arg_srcs. push ( ( src, src_ty) ) ;
501
+ }
502
+
503
+ if fn_ty. abi == Abi :: RustCall && !args. is_empty ( ) {
504
+ arg_srcs. pop ( ) ;
505
+ let last_arg = args. last ( ) . unwrap ( ) ;
506
+ let last = self . eval_operand ( last_arg) ?;
507
+ let last_ty = self . operand_ty ( last_arg) ;
508
+ let last_layout = self . type_layout ( last_ty, self . substs ( ) ) ;
509
+ match ( & last_ty. sty , last_layout) {
510
+ ( & ty:: TyTuple ( fields) ,
511
+ & Layout :: Univariant { ref variant, .. } ) => {
512
+ let offsets = iter:: once ( 0 )
513
+ . chain ( variant. offset_after_field . iter ( )
514
+ . map ( |s| s. bytes ( ) ) ) ;
515
+ for ( offset, ty) in offsets. zip ( fields) {
516
+ let src = last. offset ( offset as isize ) ;
517
+ arg_srcs. push ( ( src, ty) ) ;
518
+ }
519
+ }
520
+ ty => panic ! ( "expected tuple as last argument in function with 'rust-call' ABI, got {:?}" , ty) ,
521
+ }
522
+ }
523
+
524
+ let mir = self . load_mir ( resolved_def_id) ;
525
+ self . push_stack_frame ( def_id, span, mir, resolved_substs, return_ptr) ;
526
+
527
+ for ( i, ( src, src_ty) ) in arg_srcs. into_iter ( ) . enumerate ( ) {
528
+ let dest = self . frame ( ) . locals [ i] ;
529
+ self . move_ ( src, dest, src_ty) ?;
530
+ }
531
+
532
+ Ok ( ( ) )
533
+ }
534
+
535
+ abi => Err ( EvalError :: Unimplemented ( format ! ( "can't handle function with {:?} ABI" , abi) ) ) ,
536
+ }
537
+ }
538
+
518
539
fn drop ( & mut self , ptr : Pointer , ty : Ty < ' tcx > ) -> EvalResult < ( ) > {
519
540
if !self . type_needs_drop ( ty) {
520
541
debug ! ( "no need to drop {:?}" , ty) ;
@@ -989,12 +1010,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
989
1010
}
990
1011
991
1012
Cast ( kind, ref operand, dest_ty) => {
992
- let src = self . eval_operand ( operand) ?;
993
- let src_ty = self . operand_ty ( operand) ;
994
-
995
1013
use rustc:: mir:: repr:: CastKind :: * ;
996
1014
match kind {
997
1015
Unsize => {
1016
+ let src = self . eval_operand ( operand) ?;
1017
+ let src_ty = self . operand_ty ( operand) ;
998
1018
self . move_ ( src, dest, src_ty) ?;
999
1019
let src_pointee_ty = pointee_type ( src_ty) . unwrap ( ) ;
1000
1020
let dest_pointee_ty = pointee_type ( dest_ty) . unwrap ( ) ;
@@ -1010,11 +1030,20 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1010
1030
}
1011
1031
1012
1032
Misc => {
1033
+ let src = self . eval_operand ( operand) ?;
1013
1034
// FIXME(solson): Wrong for almost everything.
1014
1035
let size = dest_layout. size ( & self . tcx . data_layout ) . bytes ( ) as usize ;
1015
1036
self . memory . copy ( src, dest, size) ?;
1016
1037
}
1017
1038
1039
+ ReifyFnPointer => match self . operand_ty ( operand) . sty {
1040
+ ty:: TyFnDef ( def_id, substs, _) => {
1041
+ let fn_ptr = self . memory . create_fn_ptr ( def_id, substs) ;
1042
+ self . memory . write_ptr ( dest, fn_ptr) ?;
1043
+ } ,
1044
+ ref other => panic ! ( "reify fn pointer on {:?}" , other) ,
1045
+ } ,
1046
+
1018
1047
_ => return Err ( EvalError :: Unimplemented ( format ! ( "can't handle cast: {:?}" , rvalue) ) ) ,
1019
1048
}
1020
1049
}
@@ -1103,7 +1132,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1103
1132
Value { ref value } => Ok ( self . const_to_ptr ( value) ?) ,
1104
1133
Item { def_id, substs } => {
1105
1134
if let ty:: TyFnDef ( ..) = ty. sty {
1106
- Err ( EvalError :: Unimplemented ( "unimplemented: mentions of function items" . to_string ( ) ) )
1135
+ // function items are zero sized
1136
+ Ok ( self . memory . allocate ( 0 ) )
1107
1137
} else {
1108
1138
let cid = ConstantId {
1109
1139
def_id : def_id,
0 commit comments