@@ -11,14 +11,14 @@ use rustc_abi::ExternAbi;
11
11
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
12
12
use rustc_hir:: def:: Namespace ;
13
13
use rustc_hir:: def_id:: DefId ;
14
- use rustc_middle:: ty:: layout:: LayoutCx ;
14
+ use rustc_middle:: ty:: layout:: { HasTyCtxt , HasTypingEnv , LayoutCx } ;
15
15
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
16
16
use rustc_session:: config:: EntryFnType ;
17
17
18
18
use crate :: concurrency:: GenmcCtx ;
19
19
use crate :: concurrency:: thread:: TlsAllocAction ;
20
20
use crate :: diagnostics:: report_leaks;
21
- use crate :: shims:: tls;
21
+ use crate :: shims:: { global_ctor , tls} ;
22
22
use crate :: * ;
23
23
24
24
#[ derive( Copy , Clone , Debug ) ]
@@ -216,9 +216,17 @@ impl Default for MiriConfig {
216
216
}
217
217
218
218
/// The state of the main thread. Implementation detail of `on_main_stack_empty`.
219
- #[ derive( Default , Debug ) ]
219
+ #[ derive( Debug ) ]
220
220
enum MainThreadState < ' tcx > {
221
- #[ default]
221
+ GlobalCtors {
222
+ ctor_state : global_ctor:: GlobalCtorState < ' tcx > ,
223
+ /// The main function to call.
224
+ entry_id : DefId ,
225
+ entry_type : MiriEntryFnType ,
226
+ /// Arguments passed to `main`.
227
+ argc : ImmTy < ' tcx > ,
228
+ argv : ImmTy < ' tcx > ,
229
+ } ,
222
230
Running ,
223
231
TlsDtors ( tls:: TlsDtorsState < ' tcx > ) ,
224
232
Yield {
@@ -234,6 +242,15 @@ impl<'tcx> MainThreadState<'tcx> {
234
242
) -> InterpResult < ' tcx , Poll < ( ) > > {
235
243
use MainThreadState :: * ;
236
244
match self {
245
+ GlobalCtors { ctor_state, entry_id, entry_type, argc, argv } => {
246
+ match ctor_state. on_stack_empty ( this) ? {
247
+ Poll :: Pending => { } // just keep going
248
+ Poll :: Ready ( ( ) ) => {
249
+ call_main ( this, * entry_id, * entry_type, argc. clone ( ) , argv. clone ( ) ) ?;
250
+ * self = Running ;
251
+ }
252
+ }
253
+ }
237
254
Running => {
238
255
* self = TlsDtors ( Default :: default ( ) ) ;
239
256
}
@@ -309,13 +326,6 @@ pub fn create_ecx<'tcx>(
309
326
MiriMachine :: new ( config, layout_cx, genmc_ctx) ,
310
327
) ;
311
328
312
- // Some parts of initialization require a full `InterpCx`.
313
- MiriMachine :: late_init ( & mut ecx, config, {
314
- let mut state = MainThreadState :: default ( ) ;
315
- // Cannot capture anything GC-relevant here.
316
- Box :: new ( move |m| state. on_main_stack_empty ( m) )
317
- } ) ?;
318
-
319
329
// Make sure we have MIR. We check MIR for some stable monomorphic function in libcore.
320
330
let sentinel =
321
331
helpers:: try_resolve_path ( tcx, & [ "core" , "ascii" , "escape_default" ] , Namespace :: ValueNS ) ;
@@ -326,15 +336,9 @@ pub fn create_ecx<'tcx>(
326
336
) ;
327
337
}
328
338
329
- // Setup first stack frame.
330
- let entry_instance = ty:: Instance :: mono ( tcx, entry_id) ;
331
-
332
- // First argument is constructed later, because it's skipped for `miri_start.`
333
-
334
- // Second argument (argc): length of `config.args`.
339
+ // Compute argc and argv from `config.args`.
335
340
let argc =
336
341
ImmTy :: from_int ( i64:: try_from ( config. args . len ( ) ) . unwrap ( ) , ecx. machine . layouts . isize ) ;
337
- // Third argument (`argv`): created from `config.args`.
338
342
let argv = {
339
343
// Put each argument in memory, collect pointers.
340
344
let mut argvs = Vec :: < Immediate < Provenance > > :: with_capacity ( config. args . len ( ) ) ;
@@ -359,7 +363,7 @@ pub fn create_ecx<'tcx>(
359
363
ecx. write_immediate ( arg, & place) ?;
360
364
}
361
365
ecx. mark_immutable ( & argvs_place) ;
362
- // Store `argc` and `argv` for macOS `_NSGetArg{c,v}`.
366
+ // Store `argc` and `argv` for macOS `_NSGetArg{c,v}`, and for the GC to see them .
363
367
{
364
368
let argc_place =
365
369
ecx. allocate ( ecx. machine . layouts . isize , MiriMemoryKind :: Machine . into ( ) ) ?;
@@ -374,7 +378,7 @@ pub fn create_ecx<'tcx>(
374
378
ecx. machine . argv = Some ( argv_place. ptr ( ) ) ;
375
379
}
376
380
// Store command line as UTF-16 for Windows `GetCommandLineW`.
377
- {
381
+ if tcx . sess . target . os == "windows" {
378
382
// Construct a command string with all the arguments.
379
383
let cmd_utf16: Vec < u16 > = args_to_utf16_command_string ( config. args . iter ( ) ) ;
380
384
@@ -395,11 +399,43 @@ pub fn create_ecx<'tcx>(
395
399
ImmTy :: from_immediate ( imm, layout)
396
400
} ;
397
401
402
+ // Some parts of initialization require a full `InterpCx`.
403
+ MiriMachine :: late_init ( & mut ecx, config, {
404
+ let mut main_thread_state = MainThreadState :: GlobalCtors {
405
+ entry_id,
406
+ entry_type,
407
+ argc,
408
+ argv,
409
+ ctor_state : global_ctor:: GlobalCtorState :: default ( ) ,
410
+ } ;
411
+
412
+ // Cannot capture anything GC-relevant here.
413
+ // `argc` and `argv` *are* GC_relevant, but they also get stored in `machine.argc` and
414
+ // `machine.argv` so we are good.
415
+ Box :: new ( move |m| main_thread_state. on_main_stack_empty ( m) )
416
+ } ) ?;
417
+
418
+ interp_ok ( ecx)
419
+ }
420
+
421
+ // Call the entry function.
422
+ fn call_main < ' tcx > (
423
+ ecx : & mut MiriInterpCx < ' tcx > ,
424
+ entry_id : DefId ,
425
+ entry_type : MiriEntryFnType ,
426
+ argc : ImmTy < ' tcx > ,
427
+ argv : ImmTy < ' tcx > ,
428
+ ) -> InterpResult < ' tcx , ( ) > {
429
+ let tcx = ecx. tcx ( ) ;
430
+
431
+ // Setup first stack frame.
432
+ let entry_instance = ty:: Instance :: mono ( tcx, entry_id) ;
433
+
398
434
// Return place (in static memory so that it does not count as leak).
399
435
let ret_place = ecx. allocate ( ecx. machine . layouts . isize , MiriMemoryKind :: Machine . into ( ) ) ?;
400
436
ecx. machine . main_fn_ret_place = Some ( ret_place. clone ( ) ) ;
401
- // Call start function.
402
437
438
+ // Call start function.
403
439
match entry_type {
404
440
MiriEntryFnType :: Rustc ( EntryFnType :: Main { .. } ) => {
405
441
let start_id = tcx. lang_items ( ) . start_fn ( ) . unwrap_or_else ( || {
@@ -409,7 +445,7 @@ pub fn create_ecx<'tcx>(
409
445
let main_ret_ty = main_ret_ty. no_bound_vars ( ) . unwrap ( ) ;
410
446
let start_instance = ty:: Instance :: try_resolve (
411
447
tcx,
412
- typing_env,
448
+ ecx . typing_env ( ) ,
413
449
start_id,
414
450
tcx. mk_args ( & [ ty:: GenericArg :: from ( main_ret_ty) ] ) ,
415
451
)
@@ -427,7 +463,7 @@ pub fn create_ecx<'tcx>(
427
463
ExternAbi :: Rust ,
428
464
& [
429
465
ImmTy :: from_scalar (
430
- Scalar :: from_pointer ( main_ptr, & ecx) ,
466
+ Scalar :: from_pointer ( main_ptr, ecx) ,
431
467
// FIXME use a proper fn ptr type
432
468
ecx. machine . layouts . const_raw_ptr ,
433
469
) ,
@@ -450,7 +486,7 @@ pub fn create_ecx<'tcx>(
450
486
}
451
487
}
452
488
453
- interp_ok ( ecx )
489
+ interp_ok ( ( ) )
454
490
}
455
491
456
492
/// Evaluates the entry function specified by `entry_id`.
0 commit comments