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