@@ -13,6 +13,8 @@ use rustc_middle::ty::{
1313} ;
1414use rustc_target:: spec:: abi:: Abi ;
1515
16+ use rustc_session:: config:: EntryFnType ;
17+
1618use crate :: * ;
1719
1820#[ derive( Copy , Clone , Debug , PartialEq ) ]
@@ -120,12 +122,13 @@ impl Default for MiriConfig {
120122}
121123
122124/// Returns a freshly created `InterpCx`, along with an `MPlaceTy` representing
123- /// the location where the return value of the `start` lang item will be
125+ /// the location where the return value of the `start` function will be
124126/// written to.
125127/// Public because this is also used by `priroda`.
126128pub fn create_ecx < ' mir , ' tcx : ' mir > (
127129 tcx : TyCtxt < ' tcx > ,
128- main_id : DefId ,
130+ entry_id : DefId ,
131+ entry_type : EntryFnType ,
129132 config : MiriConfig ,
130133) -> InterpResult < ' tcx , ( InterpCx < ' mir , ' tcx , Evaluator < ' mir , ' tcx > > , MPlaceTy < ' tcx , Tag > ) > {
131134 let param_env = ty:: ParamEnv :: reveal_all ( ) ;
@@ -148,26 +151,10 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
148151 }
149152
150153 // Setup first stack-frame
151- let main_instance = ty:: Instance :: mono ( tcx, main_id) ;
152- let main_mir = ecx. load_mir ( main_instance. def , None ) ?;
153- if main_mir. arg_count != 0 {
154- bug ! ( "main function must not take any arguments" ) ;
155- }
154+ let entry_instance = ty:: Instance :: mono ( tcx, entry_id) ;
156155
157- let start_id = tcx. lang_items ( ) . start_fn ( ) . unwrap ( ) ;
158- let main_ret_ty = tcx. fn_sig ( main_id) . output ( ) ;
159- let main_ret_ty = main_ret_ty. no_bound_vars ( ) . unwrap ( ) ;
160- let start_instance = ty:: Instance :: resolve (
161- tcx,
162- ty:: ParamEnv :: reveal_all ( ) ,
163- start_id,
164- tcx. mk_substs ( :: std:: iter:: once ( ty:: subst:: GenericArg :: from ( main_ret_ty) ) ) ,
165- )
166- . unwrap ( )
167- . unwrap ( ) ;
156+ // First argument is constructed later, because its skipped if the entry function uses #[start]
168157
169- // First argument: pointer to `main()`.
170- let main_ptr = ecx. memory . create_fn_alloc ( FnVal :: Instance ( main_instance) ) ;
171158 // Second argument (argc): length of `config.args`.
172159 let argc = Scalar :: from_machine_usize ( u64:: try_from ( config. args . len ( ) ) . unwrap ( ) , & ecx) ;
173160 // Third argument (`argv`): created from `config.args`.
@@ -243,25 +230,58 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
243230 // Return place (in static memory so that it does not count as leak).
244231 let ret_place = ecx. allocate ( ecx. machine . layouts . isize , MiriMemoryKind :: Machine . into ( ) ) ?;
245232 // Call start function.
246- ecx. call_function (
247- start_instance,
248- Abi :: Rust ,
249- & [ Scalar :: from_pointer ( main_ptr, & ecx) . into ( ) , argc. into ( ) , argv] ,
250- Some ( & ret_place. into ( ) ) ,
251- StackPopCleanup :: None { cleanup : true } ,
252- ) ?;
233+
234+ match entry_type {
235+ EntryFnType :: Main => {
236+ let start_id = tcx. lang_items ( ) . start_fn ( ) . unwrap ( ) ;
237+ let main_ret_ty = tcx. fn_sig ( entry_id) . output ( ) ;
238+ let main_ret_ty = main_ret_ty. no_bound_vars ( ) . unwrap ( ) ;
239+ let start_instance = ty:: Instance :: resolve (
240+ tcx,
241+ ty:: ParamEnv :: reveal_all ( ) ,
242+ start_id,
243+ tcx. mk_substs ( :: std:: iter:: once ( ty:: subst:: GenericArg :: from ( main_ret_ty) ) ) ,
244+ )
245+ . unwrap ( )
246+ . unwrap ( ) ;
247+
248+ let main_ptr = ecx. memory . create_fn_alloc ( FnVal :: Instance ( entry_instance) ) ;
249+
250+ ecx. call_function (
251+ start_instance,
252+ Abi :: Rust ,
253+ & [ Scalar :: from_pointer ( main_ptr, & ecx) . into ( ) , argc. into ( ) , argv] ,
254+ Some ( & ret_place. into ( ) ) ,
255+ StackPopCleanup :: None { cleanup : true } ,
256+ ) ?;
257+ }
258+ EntryFnType :: Start => {
259+ ecx. call_function (
260+ entry_instance,
261+ Abi :: Rust ,
262+ & [ argc. into ( ) , argv] ,
263+ Some ( & ret_place. into ( ) ) ,
264+ StackPopCleanup :: None { cleanup : true } ,
265+ ) ?;
266+ }
267+ }
253268
254269 Ok ( ( ecx, ret_place) )
255270}
256271
257- /// Evaluates the main function specified by `main_id `.
272+ /// Evaluates the entry function specified by `entry_id `.
258273/// Returns `Some(return_code)` if program executed completed.
259274/// Returns `None` if an evaluation error occured.
260- pub fn eval_main < ' tcx > ( tcx : TyCtxt < ' tcx > , main_id : DefId , config : MiriConfig ) -> Option < i64 > {
275+ pub fn eval_entry < ' tcx > (
276+ tcx : TyCtxt < ' tcx > ,
277+ entry_id : DefId ,
278+ entry_type : EntryFnType ,
279+ config : MiriConfig ,
280+ ) -> Option < i64 > {
261281 // Copy setting before we move `config`.
262282 let ignore_leaks = config. ignore_leaks ;
263283
264- let ( mut ecx, ret_place) = match create_ecx ( tcx, main_id , config) {
284+ let ( mut ecx, ret_place) = match create_ecx ( tcx, entry_id , entry_type , config) {
265285 Ok ( v) => v,
266286 Err ( err) => {
267287 err. print_backtrace ( ) ;
0 commit comments