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