@@ -6,7 +6,7 @@ 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 rustc_data_structures:: indexed_vec:: Idx ;
12
12
use std:: cell:: RefCell ;
@@ -15,7 +15,7 @@ use std::rc::Rc;
15
15
use std:: { iter, mem} ;
16
16
use syntax:: ast;
17
17
use syntax:: attr;
18
- use syntax:: codemap:: { self , DUMMY_SP } ;
18
+ use syntax:: codemap:: { self , DUMMY_SP , Span } ;
19
19
20
20
use error:: { EvalError , EvalResult } ;
21
21
use memory:: { Memory , Pointer } ;
@@ -40,7 +40,7 @@ pub struct EvalContext<'a, 'tcx: 'a> {
40
40
mir_cache : RefCell < DefIdMap < Rc < mir:: Mir < ' tcx > > > > ,
41
41
42
42
/// The virtual memory system.
43
- memory : Memory ,
43
+ memory : Memory < ' tcx > ,
44
44
45
45
/// Precomputed statics, constants and promoteds
46
46
statics : HashMap < ConstantId < ' tcx > , Pointer > ,
@@ -283,6 +283,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
283
283
}
284
284
285
285
fn load_mir ( & self , def_id : DefId ) -> CachedMir < ' a , ' tcx > {
286
+ use rustc_trans:: back:: symbol_names:: def_id_to_string;
286
287
match self . tcx . map . as_local_node_id ( def_id) {
287
288
Some ( node_id) => CachedMir :: Ref ( self . mir_map . map . get ( & node_id) . unwrap ( ) ) ,
288
289
None => {
@@ -293,7 +294,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
293
294
294
295
let cs = & self . tcx . sess . cstore ;
295
296
let mir = cs. maybe_get_item_mir ( self . tcx , def_id) . unwrap_or_else ( || {
296
- panic ! ( "no mir for {:?} " , def_id) ;
297
+ panic ! ( "no mir for `{}` " , def_id_to_string ( self . tcx , def_id) ) ;
297
298
} ) ;
298
299
let cached = Rc :: new ( mir) ;
299
300
mir_cache. insert ( def_id, cached. clone ( ) ) ;
@@ -421,84 +422,17 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
421
422
422
423
let func_ty = self . operand_ty ( func) ;
423
424
match func_ty. sty {
425
+ ty:: TyFnPtr ( bare_fn_ty) => {
426
+ let ptr = self . eval_operand ( func) ?;
427
+ assert_eq ! ( ptr. offset, 0 ) ;
428
+ let fn_ptr = self . memory . read_ptr ( ptr) ?;
429
+ let ( def_id, substs) = self . memory . get_fn ( fn_ptr. alloc_id ) ?;
430
+ self . eval_fn_call ( def_id, substs, bare_fn_ty, return_ptr, args,
431
+ terminator. source_info . span ) ?
432
+ } ,
424
433
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 (
490
- def_id, terminator. source_info . span , mir, resolved_substs,
491
- return_ptr
492
- ) ;
493
-
494
- for ( i, ( src, src_ty) ) in arg_srcs. into_iter ( ) . enumerate ( ) {
495
- let dest = self . frame ( ) . locals [ i] ;
496
- self . move_ ( src, dest, src_ty) ?;
497
- }
498
- }
499
-
500
- abi => return Err ( EvalError :: Unimplemented ( format ! ( "can't handle function with {:?} ABI" , abi) ) ) ,
501
- }
434
+ self . eval_fn_call ( def_id, substs, fn_ty, return_ptr, args,
435
+ terminator. source_info . span ) ?
502
436
}
503
437
504
438
_ => return Err ( EvalError :: Unimplemented ( format ! ( "can't handle callee of type {:?}" , func_ty) ) ) ,
@@ -530,6 +464,93 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
530
464
Ok ( ( ) )
531
465
}
532
466
467
+ pub fn eval_fn_call (
468
+ & mut self ,
469
+ def_id : DefId ,
470
+ substs : & ' tcx Substs < ' tcx > ,
471
+ fn_ty : & ' tcx BareFnTy ,
472
+ return_ptr : Option < Pointer > ,
473
+ args : & [ mir:: Operand < ' tcx > ] ,
474
+ span : Span ,
475
+ ) -> EvalResult < ( ) > {
476
+ use syntax:: abi:: Abi ;
477
+ match fn_ty. abi {
478
+ Abi :: RustIntrinsic => {
479
+ let name = self . tcx . item_name ( def_id) . as_str ( ) ;
480
+ match fn_ty. sig . 0 . output {
481
+ ty:: FnConverging ( ty) => {
482
+ let size = self . type_size ( ty, self . substs ( ) ) ;
483
+ let ret = return_ptr. unwrap ( ) ;
484
+ self . call_intrinsic ( & name, substs, args, ret, size)
485
+ }
486
+ ty:: FnDiverging => unimplemented ! ( ) ,
487
+ }
488
+ }
489
+
490
+ Abi :: C => {
491
+ match fn_ty. sig . 0 . output {
492
+ ty:: FnConverging ( ty) => {
493
+ let size = self . type_size ( ty, self . substs ( ) ) ;
494
+ self . call_c_abi ( def_id, args, return_ptr. unwrap ( ) , size)
495
+ }
496
+ ty:: FnDiverging => unimplemented ! ( ) ,
497
+ }
498
+ }
499
+
500
+ Abi :: Rust | Abi :: RustCall => {
501
+ // TODO(solson): Adjust the first argument when calling a Fn or
502
+ // FnMut closure via FnOnce::call_once.
503
+
504
+ // Only trait methods can have a Self parameter.
505
+ let ( resolved_def_id, resolved_substs) = if substs. self_ty ( ) . is_some ( ) {
506
+ self . trait_method ( def_id, substs)
507
+ } else {
508
+ ( def_id, substs)
509
+ } ;
510
+
511
+ let mut arg_srcs = Vec :: new ( ) ;
512
+ for arg in args {
513
+ let src = self . eval_operand ( arg) ?;
514
+ let src_ty = self . operand_ty ( arg) ;
515
+ arg_srcs. push ( ( src, src_ty) ) ;
516
+ }
517
+
518
+ if fn_ty. abi == Abi :: RustCall && !args. is_empty ( ) {
519
+ arg_srcs. pop ( ) ;
520
+ let last_arg = args. last ( ) . unwrap ( ) ;
521
+ let last = self . eval_operand ( last_arg) ?;
522
+ let last_ty = self . operand_ty ( last_arg) ;
523
+ let last_layout = self . type_layout ( last_ty, self . substs ( ) ) ;
524
+ match ( & last_ty. sty , last_layout) {
525
+ ( & ty:: TyTuple ( fields) ,
526
+ & Layout :: Univariant { ref variant, .. } ) => {
527
+ let offsets = iter:: once ( 0 )
528
+ . chain ( variant. offset_after_field . iter ( )
529
+ . map ( |s| s. bytes ( ) ) ) ;
530
+ for ( offset, ty) in offsets. zip ( fields) {
531
+ let src = last. offset ( offset as isize ) ;
532
+ arg_srcs. push ( ( src, ty) ) ;
533
+ }
534
+ }
535
+ ty => panic ! ( "expected tuple as last argument in function with 'rust-call' ABI, got {:?}" , ty) ,
536
+ }
537
+ }
538
+
539
+ let mir = self . load_mir ( resolved_def_id) ;
540
+ self . push_stack_frame ( def_id, span, mir, resolved_substs, return_ptr) ;
541
+
542
+ for ( i, ( src, src_ty) ) in arg_srcs. into_iter ( ) . enumerate ( ) {
543
+ let dest = self . frame ( ) . locals [ i] ;
544
+ self . move_ ( src, dest, src_ty) ?;
545
+ }
546
+
547
+ Ok ( ( ) )
548
+ }
549
+
550
+ abi => Err ( EvalError :: Unimplemented ( format ! ( "can't handle function with {:?} ABI" , abi) ) ) ,
551
+ }
552
+ }
553
+
533
554
fn drop ( & mut self , ptr : Pointer , ty : Ty < ' tcx > ) -> EvalResult < ( ) > {
534
555
if !self . type_needs_drop ( ty) {
535
556
debug ! ( "no need to drop {:?}" , ty) ;
@@ -1023,12 +1044,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1023
1044
}
1024
1045
1025
1046
Cast ( kind, ref operand, dest_ty) => {
1026
- let src = self . eval_operand ( operand) ?;
1027
- let src_ty = self . operand_ty ( operand) ;
1028
-
1029
1047
use rustc:: mir:: repr:: CastKind :: * ;
1030
1048
match kind {
1031
1049
Unsize => {
1050
+ let src = self . eval_operand ( operand) ?;
1051
+ let src_ty = self . operand_ty ( operand) ;
1032
1052
self . move_ ( src, dest, src_ty) ?;
1033
1053
let src_pointee_ty = pointee_type ( src_ty) . unwrap ( ) ;
1034
1054
let dest_pointee_ty = pointee_type ( dest_ty) . unwrap ( ) ;
@@ -1044,11 +1064,20 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1044
1064
}
1045
1065
1046
1066
Misc => {
1067
+ let src = self . eval_operand ( operand) ?;
1047
1068
// FIXME(solson): Wrong for almost everything.
1048
1069
let size = dest_layout. size ( & self . tcx . data_layout ) . bytes ( ) as usize ;
1049
1070
self . memory . copy ( src, dest, size) ?;
1050
1071
}
1051
1072
1073
+ ReifyFnPointer => match self . operand_ty ( operand) . sty {
1074
+ ty:: TyFnDef ( def_id, substs, _) => {
1075
+ let fn_ptr = self . memory . create_fn_ptr ( def_id, substs) ;
1076
+ self . memory . write_ptr ( dest, fn_ptr) ?;
1077
+ } ,
1078
+ ref other => panic ! ( "reify fn pointer on {:?}" , other) ,
1079
+ } ,
1080
+
1052
1081
_ => return Err ( EvalError :: Unimplemented ( format ! ( "can't handle cast: {:?}" , rvalue) ) ) ,
1053
1082
}
1054
1083
}
@@ -1136,7 +1165,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1136
1165
Value { ref value } => Ok ( self . const_to_ptr ( value) ?) ,
1137
1166
Item { def_id, substs } => {
1138
1167
if let ty:: TyFnDef ( ..) = ty. sty {
1139
- Err ( EvalError :: Unimplemented ( "unimplemented: mentions of function items" . to_string ( ) ) )
1168
+ // function items are zero sized
1169
+ Ok ( self . memory . allocate ( 0 ) )
1140
1170
} else {
1141
1171
let cid = ConstantId {
1142
1172
def_id : def_id,
0 commit comments