@@ -113,6 +113,7 @@ pub struct CodegenCx<'a, 'tcx: 'a, B: Backend + 'static> {
113
113
}
114
114
115
115
pub struct ModuleTup < T > {
116
+ #[ allow( dead_code) ]
116
117
jit : Option < T > ,
117
118
#[ allow( dead_code) ]
118
119
faerie : Option < T > ,
@@ -234,21 +235,27 @@ impl CodegenBackend for CraneliftCodegenBackend {
234
235
tcx. sess . warn ( "Compiled everything" ) ;
235
236
236
237
tcx. sess . warn ( "Rustc codegen cranelift will JIT run the executable, because the SHOULD_RUN env var is set" ) ;
237
- let start_wrapper = tcx. lang_items ( ) . start_fn ( ) . expect ( "no start lang item" ) ;
238
238
239
- let ( name, sig) =
240
- crate :: abi:: get_function_name_and_sig ( tcx, Instance :: mono ( tcx, start_wrapper) ) ;
241
- let called_func_id = jit_module
242
- . declare_function ( & name, Linkage :: Import , & sig)
239
+ let sig = Signature {
240
+ params : vec ! [
241
+ AbiParam :: new( types:: I64 /*usize*/ ) ,
242
+ AbiParam :: new( types:: I64 /* *const _*/ ) ,
243
+ ] ,
244
+ returns : vec ! [ AbiParam :: new( types:: I64 /*isize*/ ) ] ,
245
+ call_conv : CallConv :: SystemV ,
246
+ argument_bytes : None ,
247
+ } ;
248
+ let main_func_id = jit_module
249
+ . declare_function ( "main" , Linkage :: Import , & sig)
243
250
. unwrap ( ) ;
244
251
245
- let finalized_function : * const u8 = jit_module. finalize_function ( called_func_id ) ;
252
+ let finalized_main : * const u8 = jit_module. finalize_function ( main_func_id ) ;
246
253
jit_module. finalize_all ( ) ;
247
254
tcx. sess . warn ( "Finalized everything" ) ;
248
255
249
- let f: extern "C" fn ( * const u8 , isize , * const * const u8 ) -> isize =
250
- unsafe { :: std:: mem:: transmute ( finalized_function ) } ;
251
- let res = f ( 0 as * const u8 , 0 , 0 as * const _ ) ;
256
+ let f: extern "C" fn ( isize , * const * const u8 ) -> isize =
257
+ unsafe { :: std:: mem:: transmute ( finalized_main ) } ;
258
+ let res = f ( 0 , 0 as * const _ ) ;
252
259
tcx. sess . warn ( & format ! ( "main returned {}" , res) ) ;
253
260
254
261
jit_module. finish ( ) ;
@@ -379,6 +386,8 @@ fn codegen_mono_items<'a, 'tcx: 'a>(
379
386
}
380
387
}
381
388
389
+ maybe_create_entry_wrapper ( & mut cx) ;
390
+
382
391
cx. ccx . finalize ( tcx, cx. module ) ;
383
392
384
393
let after = :: std:: time:: Instant :: now ( ) ;
@@ -396,3 +405,105 @@ fn save_incremental<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
396
405
pub fn __rustc_codegen_backend ( ) -> Box < CodegenBackend > {
397
406
Box :: new ( CraneliftCodegenBackend )
398
407
}
408
+
409
+ /// Create the `main` function which will initialize the rust runtime and call
410
+ /// users main function.
411
+ fn maybe_create_entry_wrapper ( cx : & mut CodegenCx < impl Backend + ' static > ) {
412
+ use rustc:: middle:: lang_items:: StartFnLangItem ;
413
+ use rustc:: session:: config:: EntryFnType ;
414
+
415
+ let tcx = cx. tcx ;
416
+
417
+ let ( main_def_id, use_start_lang_item) = match * tcx. sess . entry_fn . borrow ( ) {
418
+ Some ( ( id, _, entry_ty) ) => (
419
+ tcx. hir . local_def_id ( id) ,
420
+ match entry_ty {
421
+ EntryFnType :: Main => true ,
422
+ EntryFnType :: Start => false ,
423
+ } ,
424
+ ) ,
425
+ None => return ,
426
+ } ;
427
+
428
+ create_entry_fn ( tcx, cx. module , main_def_id, use_start_lang_item) ; ;
429
+
430
+ fn create_entry_fn < ' a , ' tcx : ' a > (
431
+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
432
+ m : & mut Module < impl Backend + ' static > ,
433
+ rust_main_def_id : DefId ,
434
+ use_start_lang_item : bool ,
435
+ ) {
436
+ let main_ret_ty = tcx. fn_sig ( rust_main_def_id) . output ( ) ;
437
+ // Given that `main()` has no arguments,
438
+ // then its return type cannot have
439
+ // late-bound regions, since late-bound
440
+ // regions must appear in the argument
441
+ // listing.
442
+ let main_ret_ty = tcx. erase_regions ( & main_ret_ty. no_late_bound_regions ( ) . unwrap ( ) ) ;
443
+
444
+ let cmain_sig = Signature {
445
+ params : vec ! [
446
+ AbiParam :: new( types:: I64 /*usize*/ ) ,
447
+ AbiParam :: new( types:: I64 /* *const _*/ ) ,
448
+ ] ,
449
+ returns : vec ! [ AbiParam :: new( types:: I64 /*isize*/ ) ] ,
450
+ call_conv : CallConv :: SystemV ,
451
+ argument_bytes : None ,
452
+ } ;
453
+
454
+ let cmain_func_id = m
455
+ . declare_function ( "main" , Linkage :: Export , & cmain_sig)
456
+ . unwrap ( ) ;
457
+
458
+ let instance = Instance :: mono ( tcx, rust_main_def_id) ;
459
+
460
+ let ( main_name, main_sig) = get_function_name_and_sig ( tcx, instance) ;
461
+
462
+ let main_func_id = m
463
+ . declare_function ( & main_name, Linkage :: Import , & main_sig)
464
+ . unwrap ( ) ;
465
+
466
+ let mut ctx = Context :: new ( ) ;
467
+ ctx. func = Function :: with_name_signature ( ExternalName :: user ( 0 , 0 ) , cmain_sig. clone ( ) ) ;
468
+ {
469
+ let mut func_ctx = FunctionBuilderContext :: new ( ) ;
470
+ let mut bcx: FunctionBuilder = FunctionBuilder :: new ( & mut ctx. func , & mut func_ctx) ;
471
+
472
+ let ebb = bcx. create_ebb ( ) ;
473
+ bcx. switch_to_block ( ebb) ;
474
+ let arg_argc = bcx. append_ebb_param ( ebb, types:: I64 /*usize*/ ) ;
475
+ let arg_argv = bcx. append_ebb_param ( ebb, types:: I64 /* *const _*/ ) ;
476
+
477
+ let main_func_ref = m. declare_func_in_func ( main_func_id, & mut bcx. func ) ;
478
+
479
+ let call_inst = if use_start_lang_item {
480
+ let start_def_id = tcx. require_lang_item ( StartFnLangItem ) ;
481
+ let start_instance = Instance :: resolve (
482
+ tcx,
483
+ ParamEnv :: reveal_all ( ) ,
484
+ start_def_id,
485
+ tcx. intern_substs ( & [ main_ret_ty. into ( ) ] ) ,
486
+ ) . unwrap ( ) ;
487
+
488
+ let ( start_name, start_sig) = get_function_name_and_sig ( tcx, start_instance) ;
489
+ let start_func_id = m
490
+ . declare_function ( & start_name, Linkage :: Import , & start_sig)
491
+ . unwrap ( ) ;
492
+
493
+ let main_val = bcx. ins ( ) . func_addr ( types:: I64 , main_func_ref) ;
494
+
495
+ let func_ref = m. declare_func_in_func ( start_func_id, & mut bcx. func ) ;
496
+ bcx. ins ( ) . call ( func_ref, & [ main_val, arg_argc, arg_argv] )
497
+ } else {
498
+ // using user-defined start fn
499
+ bcx. ins ( ) . call ( main_func_ref, & [ arg_argc, arg_argv] )
500
+ } ;
501
+
502
+ let result = bcx. inst_results ( call_inst) [ 0 ] ;
503
+ bcx. ins ( ) . return_ ( & [ result] ) ;
504
+ bcx. seal_all_blocks ( ) ;
505
+ bcx. finalize ( ) ;
506
+ }
507
+ m. define_function ( cmain_func_id, & mut ctx) . unwrap ( ) ;
508
+ }
509
+ }
0 commit comments