@@ -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 ( ) ) ;
@@ -429,84 +430,17 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
429
430
430
431
let func_ty = self . operand_ty ( func) ;
431
432
match func_ty. sty {
433
+ ty:: TyFnPtr ( bare_fn_ty) => {
434
+ let ptr = self . eval_operand ( func) ?;
435
+ assert_eq ! ( ptr. offset, 0 ) ;
436
+ let fn_ptr = self . memory . read_ptr ( ptr) ?;
437
+ let ( def_id, substs) = self . memory . get_fn ( fn_ptr. alloc_id ) ?;
438
+ self . eval_fn_call ( def_id, substs, bare_fn_ty, return_ptr, args,
439
+ terminator. source_info . span ) ?
440
+ } ,
432
441
ty:: TyFnDef ( def_id, substs, fn_ty) => {
433
- use syntax:: abi:: Abi ;
434
- match fn_ty. abi {
435
- Abi :: RustIntrinsic => {
436
- let name = self . tcx . item_name ( def_id) . as_str ( ) ;
437
- match fn_ty. sig . 0 . output {
438
- ty:: FnConverging ( ty) => {
439
- let size = self . type_size ( ty) ;
440
- let ret = return_ptr. unwrap ( ) ;
441
- self . call_intrinsic ( & name, substs, args, ret, size) ?
442
- }
443
- ty:: FnDiverging => unimplemented ! ( ) ,
444
- }
445
- }
446
-
447
- Abi :: C => {
448
- match fn_ty. sig . 0 . output {
449
- ty:: FnConverging ( ty) => {
450
- let size = self . type_size ( ty) ;
451
- self . call_c_abi ( def_id, args, return_ptr. unwrap ( ) , size) ?
452
- }
453
- ty:: FnDiverging => unimplemented ! ( ) ,
454
- }
455
- }
456
-
457
- Abi :: Rust | Abi :: RustCall => {
458
- // TODO(solson): Adjust the first argument when calling a Fn or
459
- // FnMut closure via FnOnce::call_once.
460
-
461
- // Only trait methods can have a Self parameter.
462
- let ( resolved_def_id, resolved_substs) = if substs. self_ty ( ) . is_some ( ) {
463
- self . trait_method ( def_id, substs)
464
- } else {
465
- ( def_id, substs)
466
- } ;
467
-
468
- let mut arg_srcs = Vec :: new ( ) ;
469
- for arg in args {
470
- let src = self . eval_operand ( arg) ?;
471
- let src_ty = self . operand_ty ( arg) ;
472
- arg_srcs. push ( ( src, src_ty) ) ;
473
- }
474
-
475
- if fn_ty. abi == Abi :: RustCall && !args. is_empty ( ) {
476
- arg_srcs. pop ( ) ;
477
- let last_arg = args. last ( ) . unwrap ( ) ;
478
- let last = self . eval_operand ( last_arg) ?;
479
- let last_ty = self . operand_ty ( last_arg) ;
480
- let last_layout = self . type_layout ( last_ty) ;
481
- match ( & last_ty. sty , last_layout) {
482
- ( & ty:: TyTuple ( fields) ,
483
- & Layout :: Univariant { ref variant, .. } ) => {
484
- let offsets = iter:: once ( 0 )
485
- . chain ( variant. offset_after_field . iter ( )
486
- . map ( |s| s. bytes ( ) ) ) ;
487
- for ( offset, ty) in offsets. zip ( fields) {
488
- let src = last. offset ( offset as isize ) ;
489
- arg_srcs. push ( ( src, ty) ) ;
490
- }
491
- }
492
- ty => panic ! ( "expected tuple as last argument in function with 'rust-call' ABI, got {:?}" , ty) ,
493
- }
494
- }
495
-
496
- let mir = self . load_mir ( resolved_def_id) ;
497
- self . push_stack_frame (
498
- def_id, terminator. source_info . span , mir, resolved_substs,
499
- return_ptr
500
- ) ;
501
-
502
- for ( i, ( src, src_ty) ) in arg_srcs. into_iter ( ) . enumerate ( ) {
503
- let dest = self . frame ( ) . locals [ i] ;
504
- self . move_ ( src, dest, src_ty) ?;
505
- }
506
- }
507
-
508
- abi => return Err ( EvalError :: Unimplemented ( format ! ( "can't handle function with {:?} ABI" , abi) ) ) ,
509
- }
442
+ self . eval_fn_call ( def_id, substs, fn_ty, return_ptr, args,
443
+ terminator. source_info . span ) ?
510
444
}
511
445
512
446
_ => return Err ( EvalError :: Unimplemented ( format ! ( "can't handle callee of type {:?}" , func_ty) ) ) ,
@@ -538,6 +472,93 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
538
472
Ok ( ( ) )
539
473
}
540
474
475
+ pub fn eval_fn_call (
476
+ & mut self ,
477
+ def_id : DefId ,
478
+ substs : & ' tcx Substs < ' tcx > ,
479
+ fn_ty : & ' tcx BareFnTy ,
480
+ return_ptr : Option < Pointer > ,
481
+ args : & [ mir:: Operand < ' tcx > ] ,
482
+ span : Span ,
483
+ ) -> EvalResult < ( ) > {
484
+ use syntax:: abi:: Abi ;
485
+ match fn_ty. abi {
486
+ Abi :: RustIntrinsic => {
487
+ let name = self . tcx . item_name ( def_id) . as_str ( ) ;
488
+ match fn_ty. sig . 0 . output {
489
+ ty:: FnConverging ( ty) => {
490
+ let size = self . type_size ( ty) ;
491
+ let ret = return_ptr. unwrap ( ) ;
492
+ self . call_intrinsic ( & name, substs, args, ret, size)
493
+ }
494
+ ty:: FnDiverging => unimplemented ! ( ) ,
495
+ }
496
+ }
497
+
498
+ Abi :: C => {
499
+ match fn_ty. sig . 0 . output {
500
+ ty:: FnConverging ( ty) => {
501
+ let size = self . type_size ( ty) ;
502
+ self . call_c_abi ( def_id, args, return_ptr. unwrap ( ) , size)
503
+ }
504
+ ty:: FnDiverging => unimplemented ! ( ) ,
505
+ }
506
+ }
507
+
508
+ Abi :: Rust | Abi :: RustCall => {
509
+ // TODO(solson): Adjust the first argument when calling a Fn or
510
+ // FnMut closure via FnOnce::call_once.
511
+
512
+ // Only trait methods can have a Self parameter.
513
+ let ( resolved_def_id, resolved_substs) = if substs. self_ty ( ) . is_some ( ) {
514
+ self . trait_method ( def_id, substs)
515
+ } else {
516
+ ( def_id, substs)
517
+ } ;
518
+
519
+ let mut arg_srcs = Vec :: new ( ) ;
520
+ for arg in args {
521
+ let src = self . eval_operand ( arg) ?;
522
+ let src_ty = self . operand_ty ( arg) ;
523
+ arg_srcs. push ( ( src, src_ty) ) ;
524
+ }
525
+
526
+ if fn_ty. abi == Abi :: RustCall && !args. is_empty ( ) {
527
+ arg_srcs. pop ( ) ;
528
+ let last_arg = args. last ( ) . unwrap ( ) ;
529
+ let last = self . eval_operand ( last_arg) ?;
530
+ let last_ty = self . operand_ty ( last_arg) ;
531
+ let last_layout = self . type_layout ( last_ty) ;
532
+ match ( & last_ty. sty , last_layout) {
533
+ ( & ty:: TyTuple ( fields) ,
534
+ & Layout :: Univariant { ref variant, .. } ) => {
535
+ let offsets = iter:: once ( 0 )
536
+ . chain ( variant. offset_after_field . iter ( )
537
+ . map ( |s| s. bytes ( ) ) ) ;
538
+ for ( offset, ty) in offsets. zip ( fields) {
539
+ let src = last. offset ( offset as isize ) ;
540
+ arg_srcs. push ( ( src, ty) ) ;
541
+ }
542
+ }
543
+ ty => panic ! ( "expected tuple as last argument in function with 'rust-call' ABI, got {:?}" , ty) ,
544
+ }
545
+ }
546
+
547
+ let mir = self . load_mir ( resolved_def_id) ;
548
+ self . push_stack_frame ( def_id, span, mir, resolved_substs, return_ptr) ;
549
+
550
+ for ( i, ( src, src_ty) ) in arg_srcs. into_iter ( ) . enumerate ( ) {
551
+ let dest = self . frame ( ) . locals [ i] ;
552
+ self . move_ ( src, dest, src_ty) ?;
553
+ }
554
+
555
+ Ok ( ( ) )
556
+ }
557
+
558
+ abi => Err ( EvalError :: Unimplemented ( format ! ( "can't handle function with {:?} ABI" , abi) ) ) ,
559
+ }
560
+ }
561
+
541
562
fn drop ( & mut self , ptr : Pointer , ty : Ty < ' tcx > ) -> EvalResult < ( ) > {
542
563
if !self . type_needs_drop ( ty) {
543
564
debug ! ( "no need to drop {:?}" , ty) ;
@@ -1033,12 +1054,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1033
1054
}
1034
1055
1035
1056
Cast ( kind, ref operand, dest_ty) => {
1036
- let src = self . eval_operand ( operand) ?;
1037
- let src_ty = self . operand_ty ( operand) ;
1038
-
1039
1057
use rustc:: mir:: repr:: CastKind :: * ;
1040
1058
match kind {
1041
1059
Unsize => {
1060
+ let src = self . eval_operand ( operand) ?;
1061
+ let src_ty = self . operand_ty ( operand) ;
1042
1062
self . move_ ( src, dest, src_ty) ?;
1043
1063
let src_pointee_ty = pointee_type ( src_ty) . unwrap ( ) ;
1044
1064
let dest_pointee_ty = pointee_type ( dest_ty) . unwrap ( ) ;
@@ -1054,6 +1074,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1054
1074
}
1055
1075
1056
1076
Misc => {
1077
+ let src = self . eval_operand ( operand) ?;
1078
+ let src_ty = self . operand_ty ( operand) ;
1057
1079
// FIXME(solson): Wrong for almost everything.
1058
1080
warn ! ( "misc cast from {:?} to {:?}" , src_ty, dest_ty) ;
1059
1081
let dest_size = self . type_size ( dest_ty) ;
@@ -1072,6 +1094,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1072
1094
}
1073
1095
}
1074
1096
1097
+ ReifyFnPointer => match self . operand_ty ( operand) . sty {
1098
+ ty:: TyFnDef ( def_id, substs, _) => {
1099
+ let fn_ptr = self . memory . create_fn_ptr ( def_id, substs) ;
1100
+ self . memory . write_ptr ( dest, fn_ptr) ?;
1101
+ } ,
1102
+ ref other => panic ! ( "reify fn pointer on {:?}" , other) ,
1103
+ } ,
1104
+
1075
1105
_ => return Err ( EvalError :: Unimplemented ( format ! ( "can't handle cast: {:?}" , rvalue) ) ) ,
1076
1106
}
1077
1107
}
@@ -1159,7 +1189,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1159
1189
Value { ref value } => Ok ( self . const_to_ptr ( value) ?) ,
1160
1190
Item { def_id, substs } => {
1161
1191
if let ty:: TyFnDef ( ..) = ty. sty {
1162
- Err ( EvalError :: Unimplemented ( "unimplemented: mentions of function items" . to_string ( ) ) )
1192
+ // function items are zero sized
1193
+ Ok ( self . memory . allocate ( 0 ) )
1163
1194
} else {
1164
1195
let cid = ConstantId {
1165
1196
def_id : def_id,
0 commit comments