@@ -6,7 +6,7 @@ use rustc::traits::{self, ProjectionMode};
66use rustc:: ty:: fold:: TypeFoldable ;
77use rustc:: ty:: layout:: { self , Layout , Size } ;
88use rustc:: ty:: subst:: { self , Subst , Substs } ;
9- use rustc:: ty:: { self , Ty , TyCtxt } ;
9+ use rustc:: ty:: { self , Ty , TyCtxt , BareFnTy } ;
1010use rustc:: util:: nodemap:: DefIdMap ;
1111use rustc_data_structures:: indexed_vec:: Idx ;
1212use std:: cell:: RefCell ;
@@ -15,7 +15,7 @@ use std::rc::Rc;
1515use std:: { iter, mem} ;
1616use syntax:: ast;
1717use syntax:: attr;
18- use syntax:: codemap:: { self , DUMMY_SP } ;
18+ use syntax:: codemap:: { self , DUMMY_SP , Span } ;
1919
2020use error:: { EvalError , EvalResult } ;
2121use memory:: { Memory , Pointer } ;
@@ -40,7 +40,7 @@ pub struct EvalContext<'a, 'tcx: 'a> {
4040 mir_cache : RefCell < DefIdMap < Rc < mir:: Mir < ' tcx > > > > ,
4141
4242 /// The virtual memory system.
43- memory : Memory ,
43+ memory : Memory < ' tcx > ,
4444
4545 /// Precomputed statics, constants and promoteds
4646 statics : HashMap < ConstantId < ' tcx > , Pointer > ,
@@ -283,6 +283,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
283283 }
284284
285285 fn load_mir ( & self , def_id : DefId ) -> CachedMir < ' a , ' tcx > {
286+ use rustc_trans:: back:: symbol_names:: def_id_to_string;
286287 match self . tcx . map . as_local_node_id ( def_id) {
287288 Some ( node_id) => CachedMir :: Ref ( self . mir_map . map . get ( & node_id) . unwrap ( ) ) ,
288289 None => {
@@ -293,7 +294,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
293294
294295 let cs = & self . tcx . sess . cstore ;
295296 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) ) ;
297298 } ) ;
298299 let cached = Rc :: new ( mir) ;
299300 mir_cache. insert ( def_id, cached. clone ( ) ) ;
@@ -429,84 +430,17 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
429430
430431 let func_ty = self . operand_ty ( func) ;
431432 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+ } ,
432441 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 ) ?
510444 }
511445
512446 _ => return Err ( EvalError :: Unimplemented ( format ! ( "can't handle callee of type {:?}" , func_ty) ) ) ,
@@ -538,6 +472,93 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
538472 Ok ( ( ) )
539473 }
540474
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+
541562 fn drop ( & mut self , ptr : Pointer , ty : Ty < ' tcx > ) -> EvalResult < ( ) > {
542563 if !self . type_needs_drop ( ty) {
543564 debug ! ( "no need to drop {:?}" , ty) ;
@@ -1033,12 +1054,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
10331054 }
10341055
10351056 Cast ( kind, ref operand, dest_ty) => {
1036- let src = self . eval_operand ( operand) ?;
1037- let src_ty = self . operand_ty ( operand) ;
1038-
10391057 use rustc:: mir:: repr:: CastKind :: * ;
10401058 match kind {
10411059 Unsize => {
1060+ let src = self . eval_operand ( operand) ?;
1061+ let src_ty = self . operand_ty ( operand) ;
10421062 self . move_ ( src, dest, src_ty) ?;
10431063 let src_pointee_ty = pointee_type ( src_ty) . unwrap ( ) ;
10441064 let dest_pointee_ty = pointee_type ( dest_ty) . unwrap ( ) ;
@@ -1054,6 +1074,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
10541074 }
10551075
10561076 Misc => {
1077+ let src = self . eval_operand ( operand) ?;
1078+ let src_ty = self . operand_ty ( operand) ;
10571079 // FIXME(solson): Wrong for almost everything.
10581080 warn ! ( "misc cast from {:?} to {:?}" , src_ty, dest_ty) ;
10591081 let dest_size = self . type_size ( dest_ty) ;
@@ -1072,6 +1094,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
10721094 }
10731095 }
10741096
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+
10751105 _ => return Err ( EvalError :: Unimplemented ( format ! ( "can't handle cast: {:?}" , rvalue) ) ) ,
10761106 }
10771107 }
@@ -1159,7 +1189,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
11591189 Value { ref value } => Ok ( self . const_to_ptr ( value) ?) ,
11601190 Item { def_id, substs } => {
11611191 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 ) )
11631194 } else {
11641195 let cid = ConstantId {
11651196 def_id : def_id,
0 commit comments