@@ -13,6 +13,8 @@ use rustc_middle::ty::{
13
13
} ;
14
14
use rustc_target:: spec:: abi:: Abi ;
15
15
16
+ use rustc_session:: config:: EntryFnType ;
17
+
16
18
use crate :: * ;
17
19
18
20
#[ derive( Copy , Clone , Debug , PartialEq ) ]
@@ -120,12 +122,13 @@ impl Default for MiriConfig {
120
122
}
121
123
122
124
/// 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
124
126
/// written to.
125
127
/// Public because this is also used by `priroda`.
126
128
pub fn create_ecx < ' mir , ' tcx : ' mir > (
127
129
tcx : TyCtxt < ' tcx > ,
128
- main_id : DefId ,
130
+ entry_id : DefId ,
131
+ entry_type : EntryFnType ,
129
132
config : MiriConfig ,
130
133
) -> InterpResult < ' tcx , ( InterpCx < ' mir , ' tcx , Evaluator < ' mir , ' tcx > > , MPlaceTy < ' tcx , Tag > ) > {
131
134
let param_env = ty:: ParamEnv :: reveal_all ( ) ;
@@ -148,26 +151,10 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
148
151
}
149
152
150
153
// 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) ;
156
155
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]
168
157
169
- // First argument: pointer to `main()`.
170
- let main_ptr = ecx. memory . create_fn_alloc ( FnVal :: Instance ( main_instance) ) ;
171
158
// Second argument (argc): length of `config.args`.
172
159
let argc = Scalar :: from_machine_usize ( u64:: try_from ( config. args . len ( ) ) . unwrap ( ) , & ecx) ;
173
160
// Third argument (`argv`): created from `config.args`.
@@ -243,25 +230,58 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
243
230
// Return place (in static memory so that it does not count as leak).
244
231
let ret_place = ecx. allocate ( ecx. machine . layouts . isize , MiriMemoryKind :: Machine . into ( ) ) ?;
245
232
// 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
+ }
253
268
254
269
Ok ( ( ecx, ret_place) )
255
270
}
256
271
257
- /// Evaluates the main function specified by `main_id `.
272
+ /// Evaluates the entry function specified by `entry_id `.
258
273
/// Returns `Some(return_code)` if program executed completed.
259
274
/// 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 > {
261
281
// Copy setting before we move `config`.
262
282
let ignore_leaks = config. ignore_leaks ;
263
283
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) {
265
285
Ok ( v) => v,
266
286
Err ( err) => {
267
287
err. print_backtrace ( ) ;
0 commit comments