@@ -126,6 +126,7 @@ impl Default for ResourceLimits {
126
126
127
127
impl < ' a , ' tcx > EvalContext < ' a , ' tcx > {
128
128
pub fn new ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , limits : ResourceLimits ) -> Self {
129
+ // Register array drop glue code
129
130
let source_info = mir:: SourceInfo {
130
131
span : DUMMY_SP ,
131
132
scope : mir:: ARGUMENT_VISIBILITY_SCOPE
@@ -852,7 +853,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
852
853
let fn_ptr = self . memory . create_fn_alloc ( instance) ;
853
854
self . write_value ( Value :: ByVal ( PrimVal :: Ptr ( fn_ptr) ) , dest, dest_ty) ?;
854
855
} ,
855
- ref other => bug ! ( "reify fn pointer on {:?}" , other) ,
856
+ ref other => bug ! ( "closure fn pointer on {:?}" , other) ,
856
857
} ,
857
858
}
858
859
}
@@ -1557,6 +1558,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1557
1558
}
1558
1559
1559
1560
pub ( super ) fn dump_local ( & self , lvalue : Lvalue < ' tcx > ) {
1561
+ // Debug output
1560
1562
if let Lvalue :: Local { frame, local, field } = lvalue {
1561
1563
let mut allocs = Vec :: new ( ) ;
1562
1564
let mut msg = format ! ( "{:?}" , local) ;
@@ -1676,62 +1678,113 @@ impl<'tcx> Frame<'tcx> {
1676
1678
1677
1679
pub fn eval_main < ' a , ' tcx : ' a > (
1678
1680
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
1679
- def_id : DefId ,
1681
+ main_id : DefId ,
1682
+ start_wrapper : Option < DefId > ,
1680
1683
limits : ResourceLimits ,
1681
1684
) {
1682
- let mut ecx = EvalContext :: new ( tcx, limits) ;
1683
- let instance = ty:: Instance :: mono ( tcx, def_id) ;
1684
- let mir = ecx. load_mir ( instance. def ) . expect ( "main function's MIR not found" ) ;
1685
-
1686
- if !mir. return_ty . is_nil ( ) || mir. arg_count != 0 {
1687
- let msg = "miri does not support main functions without `fn()` type signatures" ;
1688
- tcx. sess . err ( & EvalError :: Unimplemented ( String :: from ( msg) ) . to_string ( ) ) ;
1689
- return ;
1690
- }
1691
-
1692
- ecx. push_stack_frame (
1693
- instance,
1694
- DUMMY_SP ,
1695
- mir,
1696
- Lvalue :: from_ptr ( Pointer :: zst_ptr ( ) ) ,
1697
- StackPopCleanup :: None ,
1698
- ) . expect ( "could not allocate first stack frame" ) ;
1699
-
1700
- loop {
1701
- match ecx. step ( ) {
1702
- Ok ( true ) => { }
1703
- Ok ( false ) => {
1704
- let leaks = ecx. memory . leak_report ( ) ;
1705
- if leaks != 0 {
1706
- tcx. sess . err ( "the evaluated program leaked memory" ) ;
1707
- }
1708
- return ;
1685
+ fn run_main < ' a , ' tcx : ' a > (
1686
+ ecx : & mut EvalContext < ' a , ' tcx > ,
1687
+ main_id : DefId ,
1688
+ start_wrapper : Option < DefId > ,
1689
+ ) -> EvalResult < ' tcx > {
1690
+ let main_instance = ty:: Instance :: mono ( ecx. tcx , main_id) ;
1691
+ let main_mir = ecx. load_mir ( main_instance. def ) ?;
1692
+ let mut cleanup_ptr = None ; // Pointer to be deallocated when we are done
1693
+
1694
+ if !main_mir. return_ty . is_nil ( ) || main_mir. arg_count != 0 {
1695
+ return Err ( EvalError :: Unimplemented ( "miri does not support main functions without `fn()` type signatures" . to_owned ( ) ) ) ;
1696
+ }
1697
+
1698
+ if let Some ( start_id) = start_wrapper {
1699
+ let start_instance = ty:: Instance :: mono ( ecx. tcx , start_id) ;
1700
+ let start_mir = ecx. load_mir ( start_instance. def ) ?;
1701
+
1702
+ if start_mir. arg_count != 3 {
1703
+ return Err ( EvalError :: AbiViolation ( format ! ( "'start' lang item should have three arguments, but has {}" , start_mir. arg_count) ) ) ;
1709
1704
}
1710
- Err ( e) => {
1711
- report ( tcx, & ecx, e) ;
1712
- return ;
1705
+
1706
+ // Return value
1707
+ let ret_ptr = ecx. memory . allocate ( ecx. tcx . data_layout . pointer_size . bytes ( ) , ecx. tcx . data_layout . pointer_align . abi ( ) ) ?;
1708
+ cleanup_ptr = Some ( ret_ptr) ;
1709
+
1710
+ // Push our stack frame
1711
+ ecx. push_stack_frame (
1712
+ start_instance,
1713
+ start_mir. span ,
1714
+ start_mir,
1715
+ Lvalue :: from_ptr ( ret_ptr) ,
1716
+ StackPopCleanup :: None ,
1717
+ ) ?;
1718
+
1719
+ let mut args = ecx. frame ( ) . mir . args_iter ( ) ;
1720
+
1721
+ // First argument: pointer to main()
1722
+ let main_ptr = ecx. memory . create_fn_alloc ( main_instance) ;
1723
+ let dest = ecx. eval_lvalue ( & mir:: Lvalue :: Local ( args. next ( ) . unwrap ( ) ) ) ?;
1724
+ let main_ty = main_instance. def . def_ty ( ecx. tcx ) ;
1725
+ let main_ptr_ty = ecx. tcx . mk_fn_ptr ( main_ty. fn_sig ( ) ) ;
1726
+ ecx. write_value ( Value :: ByVal ( PrimVal :: Ptr ( main_ptr) ) , dest, main_ptr_ty) ?;
1727
+
1728
+ // Second argument (argc): 0
1729
+ let dest = ecx. eval_lvalue ( & mir:: Lvalue :: Local ( args. next ( ) . unwrap ( ) ) ) ?;
1730
+ let ty = ecx. tcx . types . isize ;
1731
+ ecx. write_value ( Value :: ByVal ( PrimVal :: Bytes ( 0 ) ) , dest, ty) ?;
1732
+
1733
+ // Third argument (argv): 0
1734
+ let dest = ecx. eval_lvalue ( & mir:: Lvalue :: Local ( args. next ( ) . unwrap ( ) ) ) ?;
1735
+ let ty = ecx. tcx . mk_imm_ptr ( ecx. tcx . mk_imm_ptr ( ecx. tcx . types . u8 ) ) ;
1736
+ ecx. write_value ( Value :: ByVal ( PrimVal :: Bytes ( 0 ) ) , dest, ty) ?;
1737
+ } else {
1738
+ ecx. push_stack_frame (
1739
+ main_instance,
1740
+ main_mir. span ,
1741
+ main_mir,
1742
+ Lvalue :: from_ptr ( Pointer :: zst_ptr ( ) ) ,
1743
+ StackPopCleanup :: None ,
1744
+ ) ?;
1745
+ }
1746
+
1747
+ while ecx. step ( ) ? { }
1748
+ if let Some ( cleanup_ptr) = cleanup_ptr {
1749
+ ecx. memory . deallocate ( cleanup_ptr) ?;
1750
+ }
1751
+ return Ok ( ( ) ) ;
1752
+ }
1753
+
1754
+ let mut ecx = EvalContext :: new ( tcx, limits) ;
1755
+ match run_main ( & mut ecx, main_id, start_wrapper) {
1756
+ Ok ( ( ) ) => {
1757
+ let leaks = ecx. memory . leak_report ( ) ;
1758
+ if leaks != 0 {
1759
+ tcx. sess . err ( "the evaluated program leaked memory" ) ;
1713
1760
}
1714
1761
}
1762
+ Err ( e) => {
1763
+ report ( tcx, & ecx, e) ;
1764
+ }
1715
1765
}
1716
1766
}
1717
1767
1718
1768
fn report ( tcx : TyCtxt , ecx : & EvalContext , e : EvalError ) {
1719
- let frame = ecx. stack ( ) . last ( ) . expect ( "stackframe was empty" ) ;
1720
- let block = & frame. mir . basic_blocks ( ) [ frame. block ] ;
1721
- let span = if frame. stmt < block. statements . len ( ) {
1722
- block. statements [ frame. stmt ] . source_info . span
1723
- } else {
1724
- block. terminator ( ) . source_info . span
1725
- } ;
1726
- let mut err = tcx. sess . struct_span_err ( span, & e. to_string ( ) ) ;
1727
- for & Frame { instance, span, .. } in ecx. stack ( ) . iter ( ) . rev ( ) {
1728
- if tcx. def_key ( instance. def_id ( ) ) . disambiguated_data . data == DefPathData :: ClosureExpr {
1729
- err. span_note ( span, "inside call to closure" ) ;
1730
- continue ;
1769
+ if let Some ( frame) = ecx. stack ( ) . last ( ) {
1770
+ let block = & frame. mir . basic_blocks ( ) [ frame. block ] ;
1771
+ let span = if frame. stmt < block. statements . len ( ) {
1772
+ block. statements [ frame. stmt ] . source_info . span
1773
+ } else {
1774
+ block. terminator ( ) . source_info . span
1775
+ } ;
1776
+ let mut err = tcx. sess . struct_span_err ( span, & e. to_string ( ) ) ;
1777
+ for & Frame { instance, span, .. } in ecx. stack ( ) . iter ( ) . rev ( ) {
1778
+ if tcx. def_key ( instance. def_id ( ) ) . disambiguated_data . data == DefPathData :: ClosureExpr {
1779
+ err. span_note ( span, "inside call to closure" ) ;
1780
+ continue ;
1781
+ }
1782
+ err. span_note ( span, & format ! ( "inside call to {}" , instance) ) ;
1731
1783
}
1732
- err. span_note ( span, & format ! ( "inside call to {}" , instance) ) ;
1784
+ err. emit ( ) ;
1785
+ } else {
1786
+ tcx. sess . err ( & e. to_string ( ) ) ;
1733
1787
}
1734
- err. emit ( ) ;
1735
1788
}
1736
1789
1737
1790
// TODO(solson): Upstream these methods into rustc::ty::layout.
0 commit comments