]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_cranelift/src/main_shim.rs
Auto merge of #78323 - est31:smaller_list_overlap, r=varkor
[rust.git] / compiler / rustc_codegen_cranelift / src / main_shim.rs
1 use rustc_hir::LangItem;
2 use rustc_session::config::EntryFnType;
3
4 use crate::prelude::*;
5
6 /// Create the `main` function which will initialize the rust runtime and call
7 /// users main function.
8 pub(crate) fn maybe_create_entry_wrapper(
9     tcx: TyCtxt<'_>,
10     module: &mut impl Module,
11     unwind_context: &mut UnwindContext<'_>,
12     use_jit: bool,
13 ) {
14     let (main_def_id, use_start_lang_item) = match tcx.entry_fn(LOCAL_CRATE) {
15         Some((def_id, entry_ty)) => (
16             def_id.to_def_id(),
17             match entry_ty {
18                 EntryFnType::Main => true,
19                 EntryFnType::Start => false,
20             },
21         ),
22         None => return,
23     };
24
25     let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx);
26     if module.get_name(&*tcx.symbol_name(instance).name).is_none() {
27         return;
28     }
29
30     create_entry_fn(
31         tcx,
32         module,
33         unwind_context,
34         main_def_id,
35         use_start_lang_item,
36         use_jit,
37     );
38
39     fn create_entry_fn(
40         tcx: TyCtxt<'_>,
41         m: &mut impl Module,
42         unwind_context: &mut UnwindContext<'_>,
43         rust_main_def_id: DefId,
44         use_start_lang_item: bool,
45         use_jit: bool,
46     ) {
47         let main_ret_ty = tcx.fn_sig(rust_main_def_id).output();
48         // Given that `main()` has no arguments,
49         // then its return type cannot have
50         // late-bound regions, since late-bound
51         // regions must appear in the argument
52         // listing.
53         let main_ret_ty = tcx.erase_regions(&main_ret_ty.no_bound_vars().unwrap());
54
55         let cmain_sig = Signature {
56             params: vec![
57                 AbiParam::new(m.target_config().pointer_type()),
58                 AbiParam::new(m.target_config().pointer_type()),
59             ],
60             returns: vec![AbiParam::new(
61                 m.target_config().pointer_type(), /*isize*/
62             )],
63             call_conv: CallConv::triple_default(m.isa().triple()),
64         };
65
66         let cmain_func_id = m
67             .declare_function("main", Linkage::Export, &cmain_sig)
68             .unwrap();
69
70         let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx);
71
72         let (main_name, main_sig) =
73             get_function_name_and_sig(tcx, m.isa().triple(), instance, false);
74         let main_func_id = m
75             .declare_function(&main_name, Linkage::Import, &main_sig)
76             .unwrap();
77
78         let mut ctx = Context::new();
79         ctx.func = Function::with_name_signature(ExternalName::user(0, 0), cmain_sig.clone());
80         {
81             let mut func_ctx = FunctionBuilderContext::new();
82             let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
83
84             let block = bcx.create_block();
85             bcx.switch_to_block(block);
86             let arg_argc = bcx.append_block_param(block, m.target_config().pointer_type());
87             let arg_argv = bcx.append_block_param(block, m.target_config().pointer_type());
88
89             crate::atomic_shim::init_global_lock(m, &mut bcx, use_jit);
90
91             let main_func_ref = m.declare_func_in_func(main_func_id, &mut bcx.func);
92
93             let call_inst = if use_start_lang_item {
94                 let start_def_id = tcx.require_lang_item(LangItem::Start, None);
95                 let start_instance = Instance::resolve(
96                     tcx,
97                     ParamEnv::reveal_all(),
98                     start_def_id,
99                     tcx.intern_substs(&[main_ret_ty.into()]),
100                 )
101                 .unwrap()
102                 .unwrap()
103                 .polymorphize(tcx);
104                 let start_func_id = import_function(tcx, m, start_instance);
105
106                 let main_val = bcx
107                     .ins()
108                     .func_addr(m.target_config().pointer_type(), main_func_ref);
109
110                 let func_ref = m.declare_func_in_func(start_func_id, &mut bcx.func);
111                 bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv])
112             } else {
113                 // using user-defined start fn
114                 bcx.ins().call(main_func_ref, &[arg_argc, arg_argv])
115             };
116
117             let result = bcx.inst_results(call_inst)[0];
118             bcx.ins().return_(&[result]);
119             bcx.seal_all_blocks();
120             bcx.finalize();
121         }
122         m.define_function(
123             cmain_func_id,
124             &mut ctx,
125             &mut cranelift_codegen::binemit::NullTrapSink {},
126         )
127         .unwrap();
128         unwind_context.add_function(cmain_func_id, &ctx, m.isa());
129     }
130 }