@@ -10,6 +10,8 @@ use rustc_middle::ty::{self, layout::LayoutCx, TyCtxt};
10
10
use rustc_target:: abi:: LayoutOf ;
11
11
use rustc_target:: spec:: abi:: Abi ;
12
12
13
+ use rustc_session:: config:: EntryFnType ;
14
+
13
15
use crate :: * ;
14
16
15
17
#[ derive( Copy , Clone , Debug , PartialEq ) ]
@@ -117,12 +119,13 @@ impl Default for MiriConfig {
117
119
}
118
120
119
121
/// 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
121
123
/// written to.
122
124
/// Public because this is also used by `priroda`.
123
125
pub fn create_ecx < ' mir , ' tcx : ' mir > (
124
126
tcx : TyCtxt < ' tcx > ,
125
- main_id : DefId ,
127
+ entry_id : DefId ,
128
+ entry_type : EntryFnType ,
126
129
config : MiriConfig ,
127
130
) -> InterpResult < ' tcx , ( InterpCx < ' mir , ' tcx , Evaluator < ' mir , ' tcx > > , MPlaceTy < ' tcx , Tag > ) > {
128
131
let param_env = ty:: ParamEnv :: reveal_all ( ) ;
@@ -145,26 +148,14 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
145
148
}
146
149
147
150
// 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)?;
150
153
if main_mir.arg_count != 0 {
151
154
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]
153
158
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) ) ;
168
159
// Second argument (argc): length of `config.args`.
169
160
let argc = Scalar :: from_machine_usize ( u64:: try_from ( config. args . len ( ) ) . unwrap ( ) , & ecx) ;
170
161
// Third argument (`argv`): created from `config.args`.
@@ -237,28 +228,71 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
237
228
argv
238
229
} ;
239
230
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
+
240
241
// Return place (in static memory so that it does not count as leak).
241
242
let ret_place = ecx. allocate ( ecx. machine . layouts . isize , MiriMemoryKind :: Machine . into ( ) ) ?;
242
243
// 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
+ }
250
279
251
280
Ok ( ( ecx, ret_place) )
252
281
}
253
282
254
- /// Evaluates the main function specified by `main_id `.
283
+ /// Evaluates the entry function specified by `entry_id `.
255
284
/// Returns `Some(return_code)` if program executed completed.
256
285
/// 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 > {
258
292
// Copy setting before we move `config`.
259
293
let ignore_leaks = config. ignore_leaks ;
260
294
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) {
262
296
Ok ( v) => v,
263
297
Err ( err) => {
264
298
err. print_backtrace ( ) ;
0 commit comments