]>
Commit | Line | Data |
---|---|---|
29967ef6 | 1 | use rustc_hir::LangItem; |
17df50a5 XL |
2 | use rustc_middle::ty::subst::GenericArg; |
3 | use rustc_middle::ty::AssocKind; | |
29967ef6 | 4 | use rustc_session::config::EntryFnType; |
17df50a5 | 5 | use rustc_span::symbol::Ident; |
29967ef6 XL |
6 | |
7 | use crate::prelude::*; | |
8 | ||
9 | /// Create the `main` function which will initialize the rust runtime and call | |
10 | /// users main function. | |
11 | pub(crate) fn maybe_create_entry_wrapper( | |
12 | tcx: TyCtxt<'_>, | |
13 | module: &mut impl Module, | |
17df50a5 XL |
14 | unwind_context: &mut UnwindContext, |
15 | is_jit: bool, | |
16 | is_primary_cgu: bool, | |
29967ef6 | 17 | ) { |
17df50a5 | 18 | let (main_def_id, is_main_fn) = match tcx.entry_fn(()) { |
29967ef6 | 19 | Some((def_id, entry_ty)) => ( |
cdc7bbd5 | 20 | def_id, |
29967ef6 XL |
21 | match entry_ty { |
22 | EntryFnType::Main => true, | |
23 | EntryFnType::Start => false, | |
24 | }, | |
25 | ), | |
26 | None => return, | |
27 | }; | |
28 | ||
17df50a5 XL |
29 | if main_def_id.is_local() { |
30 | let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx); | |
31 | if !is_jit && module.get_name(&*tcx.symbol_name(instance).name).is_none() { | |
32 | return; | |
33 | } | |
34 | } else if !is_primary_cgu { | |
29967ef6 XL |
35 | return; |
36 | } | |
37 | ||
17df50a5 | 38 | create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn); |
29967ef6 XL |
39 | |
40 | fn create_entry_fn( | |
41 | tcx: TyCtxt<'_>, | |
42 | m: &mut impl Module, | |
17df50a5 | 43 | unwind_context: &mut UnwindContext, |
29967ef6 | 44 | rust_main_def_id: DefId, |
17df50a5 XL |
45 | ignore_lang_start_wrapper: bool, |
46 | is_main_fn: bool, | |
29967ef6 XL |
47 | ) { |
48 | let main_ret_ty = tcx.fn_sig(rust_main_def_id).output(); | |
49 | // Given that `main()` has no arguments, | |
50 | // then its return type cannot have | |
51 | // late-bound regions, since late-bound | |
52 | // regions must appear in the argument | |
53 | // listing. | |
5e7ed085 FG |
54 | let main_ret_ty = tcx.normalize_erasing_regions( |
55 | ty::ParamEnv::reveal_all(), | |
56 | main_ret_ty.no_bound_vars().unwrap(), | |
57 | ); | |
29967ef6 XL |
58 | |
59 | let cmain_sig = Signature { | |
60 | params: vec![ | |
61 | AbiParam::new(m.target_config().pointer_type()), | |
62 | AbiParam::new(m.target_config().pointer_type()), | |
63 | ], | |
6a06907d | 64 | returns: vec![AbiParam::new(m.target_config().pointer_type() /*isize*/)], |
29967ef6 XL |
65 | call_conv: CallConv::triple_default(m.isa().triple()), |
66 | }; | |
67 | ||
6a06907d | 68 | let cmain_func_id = m.declare_function("main", Linkage::Export, &cmain_sig).unwrap(); |
29967ef6 XL |
69 | |
70 | let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx); | |
71 | ||
17df50a5 | 72 | let main_name = tcx.symbol_name(instance).name; |
5869c6ff | 73 | let main_sig = get_function_sig(tcx, m.isa().triple(), instance); |
17df50a5 | 74 | let main_func_id = m.declare_function(main_name, Linkage::Import, &main_sig).unwrap(); |
29967ef6 XL |
75 | |
76 | let mut ctx = Context::new(); | |
77 | ctx.func = Function::with_name_signature(ExternalName::user(0, 0), cmain_sig); | |
78 | { | |
79 | let mut func_ctx = FunctionBuilderContext::new(); | |
80 | let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); | |
81 | ||
82 | let block = bcx.create_block(); | |
83 | bcx.switch_to_block(block); | |
84 | let arg_argc = bcx.append_block_param(block, m.target_config().pointer_type()); | |
85 | let arg_argv = bcx.append_block_param(block, m.target_config().pointer_type()); | |
86 | ||
29967ef6 XL |
87 | let main_func_ref = m.declare_func_in_func(main_func_id, &mut bcx.func); |
88 | ||
17df50a5 XL |
89 | let result = if is_main_fn && ignore_lang_start_wrapper { |
90 | // regular main fn, but ignoring #[lang = "start"] as we are running in the jit | |
91 | // FIXME set program arguments somehow | |
92 | let call_inst = bcx.ins().call(main_func_ref, &[]); | |
93 | let call_results = bcx.func.dfg.inst_results(call_inst).to_owned(); | |
94 | ||
95 | let termination_trait = tcx.require_lang_item(LangItem::Termination, None); | |
96 | let report = tcx | |
97 | .associated_items(termination_trait) | |
98 | .find_by_name_and_kind( | |
99 | tcx, | |
100 | Ident::from_str("report"), | |
101 | AssocKind::Fn, | |
102 | termination_trait, | |
103 | ) | |
104 | .unwrap(); | |
105 | let report = Instance::resolve( | |
106 | tcx, | |
107 | ParamEnv::reveal_all(), | |
108 | report.def_id, | |
109 | tcx.mk_substs([GenericArg::from(main_ret_ty)].iter()), | |
110 | ) | |
111 | .unwrap() | |
112 | .unwrap(); | |
113 | ||
114 | let report_name = tcx.symbol_name(report).name; | |
115 | let report_sig = get_function_sig(tcx, m.isa().triple(), report); | |
116 | let report_func_id = | |
117 | m.declare_function(report_name, Linkage::Import, &report_sig).unwrap(); | |
118 | let report_func_ref = m.declare_func_in_func(report_func_id, &mut bcx.func); | |
119 | ||
120 | // FIXME do proper abi handling instead of expecting the pass mode to be identical | |
121 | // for returns and arguments. | |
122 | let report_call_inst = bcx.ins().call(report_func_ref, &call_results); | |
123 | let res = bcx.func.dfg.inst_results(report_call_inst)[0]; | |
124 | match m.target_config().pointer_type() { | |
125 | types::I32 => res, | |
126 | types::I64 => bcx.ins().sextend(types::I64, res), | |
127 | _ => unimplemented!("16bit systems are not yet supported"), | |
128 | } | |
129 | } else if is_main_fn { | |
29967ef6 XL |
130 | let start_def_id = tcx.require_lang_item(LangItem::Start, None); |
131 | let start_instance = Instance::resolve( | |
132 | tcx, | |
133 | ParamEnv::reveal_all(), | |
134 | start_def_id, | |
135 | tcx.intern_substs(&[main_ret_ty.into()]), | |
136 | ) | |
137 | .unwrap() | |
138 | .unwrap() | |
139 | .polymorphize(tcx); | |
140 | let start_func_id = import_function(tcx, m, start_instance); | |
141 | ||
6a06907d | 142 | let main_val = bcx.ins().func_addr(m.target_config().pointer_type(), main_func_ref); |
29967ef6 XL |
143 | |
144 | let func_ref = m.declare_func_in_func(start_func_id, &mut bcx.func); | |
17df50a5 XL |
145 | let call_inst = bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv]); |
146 | bcx.inst_results(call_inst)[0] | |
29967ef6 XL |
147 | } else { |
148 | // using user-defined start fn | |
17df50a5 XL |
149 | let call_inst = bcx.ins().call(main_func_ref, &[arg_argc, arg_argv]); |
150 | bcx.inst_results(call_inst)[0] | |
29967ef6 XL |
151 | }; |
152 | ||
29967ef6 XL |
153 | bcx.ins().return_(&[result]); |
154 | bcx.seal_all_blocks(); | |
155 | bcx.finalize(); | |
156 | } | |
5e7ed085 | 157 | m.define_function(cmain_func_id, &mut ctx).unwrap(); |
29967ef6 XL |
158 | unwind_context.add_function(cmain_func_id, &ctx, m.isa()); |
159 | } | |
160 | } |