@@ -10,6 +10,8 @@ use rustc_middle::ty::{self, layout::LayoutCx, TyCtxt};
1010use rustc_target:: abi:: LayoutOf ;
1111use rustc_target:: spec:: abi:: Abi ;
1212
13+ use rustc_session:: config:: EntryFnType ;
14+
1315use crate :: * ;
1416
1517#[ derive( Copy , Clone , Debug , PartialEq ) ]
@@ -117,12 +119,13 @@ impl Default for MiriConfig {
117119}
118120
119121/// Returns a freshly created `InterpCx`, along with an `MPlaceTy` representing
120- /// the location where the return value of the `start` lang item will be
122+ /// the location where the return value of the `start` function will be
121123/// written to.
122124/// Public because this is also used by `priroda`.
123125pub fn create_ecx < ' mir , ' tcx : ' mir > (
124126 tcx : TyCtxt < ' tcx > ,
125- main_id : DefId ,
127+ entry_id : DefId ,
128+ entry_type : EntryFnType ,
126129 config : MiriConfig ,
127130) -> InterpResult < ' tcx , ( InterpCx < ' mir , ' tcx , Evaluator < ' mir , ' tcx > > , MPlaceTy < ' tcx , Tag > ) > {
128131 let param_env = ty:: ParamEnv :: reveal_all ( ) ;
@@ -145,26 +148,14 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
145148 }
146149
147150 // Setup first stack-frame
148- let main_instance = ty:: Instance :: mono ( tcx, main_id ) ;
149- let main_mir = ecx. load_mir ( main_instance . def , None ) ?;
151+ let entry_instance = ty:: Instance :: mono ( tcx, entry_id ) ;
152+ /* let entry_mir = ecx.load_mir(entry_instance .def, None)?;
150153 if main_mir.arg_count != 0 {
151154 bug!("main function must not take any arguments");
152- }
155+ }*/
156+
157+ // First argument is constructed later, because its skipped if the entry function uses #[start]
153158
154- let start_id = tcx. lang_items ( ) . start_fn ( ) . unwrap ( ) ;
155- let main_ret_ty = tcx. fn_sig ( main_id) . output ( ) ;
156- let main_ret_ty = main_ret_ty. no_bound_vars ( ) . unwrap ( ) ;
157- let start_instance = ty:: Instance :: resolve (
158- tcx,
159- ty:: ParamEnv :: reveal_all ( ) ,
160- start_id,
161- tcx. mk_substs ( :: std:: iter:: once ( ty:: subst:: GenericArg :: from ( main_ret_ty) ) ) ,
162- )
163- . unwrap ( )
164- . unwrap ( ) ;
165-
166- // First argument: pointer to `main()`.
167- let main_ptr = ecx. memory . create_fn_alloc ( FnVal :: Instance ( main_instance) ) ;
168159 // Second argument (argc): length of `config.args`.
169160 let argc = Scalar :: from_machine_usize ( u64:: try_from ( config. args . len ( ) ) . unwrap ( ) , & ecx) ;
170161 // Third argument (`argv`): created from `config.args`.
@@ -237,28 +228,71 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
237228 argv
238229 } ;
239230
231+ /*let args: &[_] = match entry_type {
232+ EntryFnType::Main => {
233+ // First argument: pointer to `main()`.
234+ let main_ptr = ecx.memory.create_fn_alloc(FnVal::Instance(main_instance));
235+
236+ &[Scalar::from_pointer(main_ptr, &ecx).into(), argc.into(), argv]
237+ }
238+ EntryFnType::Start => &[argc.into(), argv],
239+ };*/
240+
240241 // Return place (in static memory so that it does not count as leak).
241242 let ret_place = ecx. allocate ( ecx. machine . layouts . isize , MiriMemoryKind :: Machine . into ( ) ) ?;
242243 // Call start function.
243- ecx. call_function (
244- start_instance,
245- Abi :: Rust ,
246- & [ Scalar :: from_pointer ( main_ptr, & ecx) . into ( ) , argc. into ( ) , argv] ,
247- Some ( & ret_place. into ( ) ) ,
248- StackPopCleanup :: None { cleanup : true } ,
249- ) ?;
244+
245+ match entry_type {
246+ EntryFnType :: Main => {
247+ let start_id = tcx. lang_items ( ) . start_fn ( ) . unwrap ( ) ;
248+ let main_ret_ty = tcx. fn_sig ( entry_id) . output ( ) ;
249+ let main_ret_ty = main_ret_ty. no_bound_vars ( ) . unwrap ( ) ;
250+ let start_instance = ty:: Instance :: resolve (
251+ tcx,
252+ ty:: ParamEnv :: reveal_all ( ) ,
253+ start_id,
254+ tcx. mk_substs ( :: std:: iter:: once ( ty:: subst:: GenericArg :: from ( main_ret_ty) ) ) ,
255+ )
256+ . unwrap ( )
257+ . unwrap ( ) ;
258+
259+ let main_ptr = ecx. memory . create_fn_alloc ( FnVal :: Instance ( entry_instance) ) ;
260+
261+ ecx. call_function (
262+ start_instance,
263+ Abi :: Rust ,
264+ & [ Scalar :: from_pointer ( main_ptr, & ecx) . into ( ) , argc. into ( ) , argv] ,
265+ Some ( & ret_place. into ( ) ) ,
266+ StackPopCleanup :: None { cleanup : true } ,
267+ ) ?;
268+ }
269+ EntryFnType :: Start => {
270+ ecx. call_function (
271+ entry_instance,
272+ Abi :: Rust ,
273+ & [ argc. into ( ) , argv] ,
274+ Some ( & ret_place. into ( ) ) ,
275+ StackPopCleanup :: None { cleanup : true } ,
276+ ) ?;
277+ }
278+ }
250279
251280 Ok ( ( ecx, ret_place) )
252281}
253282
254- /// Evaluates the main function specified by `main_id `.
283+ /// Evaluates the entry function specified by `entry_id `.
255284/// Returns `Some(return_code)` if program executed completed.
256285/// Returns `None` if an evaluation error occured.
257- pub fn eval_main < ' tcx > ( tcx : TyCtxt < ' tcx > , main_id : DefId , config : MiriConfig ) -> Option < i64 > {
286+ pub fn eval_entry < ' tcx > (
287+ tcx : TyCtxt < ' tcx > ,
288+ entry_id : DefId ,
289+ entry_type : EntryFnType ,
290+ config : MiriConfig ,
291+ ) -> Option < i64 > {
258292 // Copy setting before we move `config`.
259293 let ignore_leaks = config. ignore_leaks ;
260294
261- let ( mut ecx, ret_place) = match create_ecx ( tcx, main_id , config) {
295+ let ( mut ecx, ret_place) = match create_ecx ( tcx, entry_id , entry_type , config) {
262296 Ok ( v) => v,
263297 Err ( err) => {
264298 err. print_backtrace ( ) ;
0 commit comments