]>
Commit | Line | Data |
---|---|---|
29967ef6 XL |
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<'_>, | |
29967ef6 XL |
12 | ) { |
13 | let (main_def_id, use_start_lang_item) = match tcx.entry_fn(LOCAL_CRATE) { | |
14 | Some((def_id, entry_ty)) => ( | |
15 | def_id.to_def_id(), | |
16 | match entry_ty { | |
17 | EntryFnType::Main => true, | |
18 | EntryFnType::Start => false, | |
19 | }, | |
20 | ), | |
21 | None => return, | |
22 | }; | |
23 | ||
24 | let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx); | |
25 | if module.get_name(&*tcx.symbol_name(instance).name).is_none() { | |
26 | return; | |
27 | } | |
28 | ||
6a06907d | 29 | create_entry_fn(tcx, module, unwind_context, main_def_id, use_start_lang_item); |
29967ef6 XL |
30 | |
31 | fn create_entry_fn( | |
32 | tcx: TyCtxt<'_>, | |
33 | m: &mut impl Module, | |
34 | unwind_context: &mut UnwindContext<'_>, | |
35 | rust_main_def_id: DefId, | |
36 | use_start_lang_item: bool, | |
29967ef6 XL |
37 | ) { |
38 | let main_ret_ty = tcx.fn_sig(rust_main_def_id).output(); | |
39 | // Given that `main()` has no arguments, | |
40 | // then its return type cannot have | |
41 | // late-bound regions, since late-bound | |
42 | // regions must appear in the argument | |
43 | // listing. | |
fc512014 | 44 | let main_ret_ty = tcx.erase_regions(main_ret_ty.no_bound_vars().unwrap()); |
29967ef6 XL |
45 | |
46 | let cmain_sig = Signature { | |
47 | params: vec![ | |
48 | AbiParam::new(m.target_config().pointer_type()), | |
49 | AbiParam::new(m.target_config().pointer_type()), | |
50 | ], | |
6a06907d | 51 | returns: vec![AbiParam::new(m.target_config().pointer_type() /*isize*/)], |
29967ef6 XL |
52 | call_conv: CallConv::triple_default(m.isa().triple()), |
53 | }; | |
54 | ||
6a06907d | 55 | let cmain_func_id = m.declare_function("main", Linkage::Export, &cmain_sig).unwrap(); |
29967ef6 XL |
56 | |
57 | let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx); | |
58 | ||
5869c6ff XL |
59 | let main_name = tcx.symbol_name(instance).name.to_string(); |
60 | let main_sig = get_function_sig(tcx, m.isa().triple(), instance); | |
6a06907d | 61 | let main_func_id = m.declare_function(&main_name, Linkage::Import, &main_sig).unwrap(); |
29967ef6 XL |
62 | |
63 | let mut ctx = Context::new(); | |
64 | ctx.func = Function::with_name_signature(ExternalName::user(0, 0), cmain_sig); | |
65 | { | |
66 | let mut func_ctx = FunctionBuilderContext::new(); | |
67 | let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); | |
68 | ||
69 | let block = bcx.create_block(); | |
70 | bcx.switch_to_block(block); | |
71 | let arg_argc = bcx.append_block_param(block, m.target_config().pointer_type()); | |
72 | let arg_argv = bcx.append_block_param(block, m.target_config().pointer_type()); | |
73 | ||
29967ef6 XL |
74 | let main_func_ref = m.declare_func_in_func(main_func_id, &mut bcx.func); |
75 | ||
76 | let call_inst = if use_start_lang_item { | |
77 | let start_def_id = tcx.require_lang_item(LangItem::Start, None); | |
78 | let start_instance = Instance::resolve( | |
79 | tcx, | |
80 | ParamEnv::reveal_all(), | |
81 | start_def_id, | |
82 | tcx.intern_substs(&[main_ret_ty.into()]), | |
83 | ) | |
84 | .unwrap() | |
85 | .unwrap() | |
86 | .polymorphize(tcx); | |
87 | let start_func_id = import_function(tcx, m, start_instance); | |
88 | ||
6a06907d | 89 | let main_val = bcx.ins().func_addr(m.target_config().pointer_type(), main_func_ref); |
29967ef6 XL |
90 | |
91 | let func_ref = m.declare_func_in_func(start_func_id, &mut bcx.func); | |
92 | bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv]) | |
93 | } else { | |
94 | // using user-defined start fn | |
95 | bcx.ins().call(main_func_ref, &[arg_argc, arg_argv]) | |
96 | }; | |
97 | ||
98 | let result = bcx.inst_results(call_inst)[0]; | |
99 | bcx.ins().return_(&[result]); | |
100 | bcx.seal_all_blocks(); | |
101 | bcx.finalize(); | |
102 | } | |
103 | m.define_function( | |
104 | cmain_func_id, | |
105 | &mut ctx, | |
106 | &mut cranelift_codegen::binemit::NullTrapSink {}, | |
107 | ) | |
108 | .unwrap(); | |
109 | unwind_context.add_function(cmain_func_id, &ctx, m.isa()); | |
110 | } | |
111 | } |