1 use cranelift_codegen
::binemit
::{NullStackMapSink, NullTrapSink}
;
2 use rustc_hir
::LangItem
;
3 use rustc_middle
::ty
::subst
::GenericArg
;
4 use rustc_middle
::ty
::AssocKind
;
5 use rustc_session
::config
::EntryFnType
;
6 use rustc_span
::symbol
::Ident
;
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(
14 module
: &mut impl Module
,
15 unwind_context
: &mut UnwindContext
,
19 let (main_def_id
, is_main_fn
) = match tcx
.entry_fn(()) {
20 Some((def_id
, entry_ty
)) => (
23 EntryFnType
::Main
=> true,
24 EntryFnType
::Start
=> false,
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() {
35 } else if !is_primary_cgu
{
39 create_entry_fn(tcx
, module
, unwind_context
, main_def_id
, is_jit
, is_main_fn
);
44 unwind_context
: &mut UnwindContext
,
45 rust_main_def_id
: DefId
,
46 ignore_lang_start_wrapper
: bool
,
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
55 let main_ret_ty
= tcx
.erase_regions(main_ret_ty
.no_bound_vars().unwrap());
57 let cmain_sig
= Signature
{
59 AbiParam
::new(m
.target_config().pointer_type()),
60 AbiParam
::new(m
.target_config().pointer_type()),
62 returns
: vec
![AbiParam
::new(m
.target_config().pointer_type() /*isize*/)],
63 call_conv
: CallConv
::triple_default(m
.isa().triple()),
66 let cmain_func_id
= m
.declare_function("main", Linkage
::Export
, &cmain_sig
).unwrap();
68 let instance
= Instance
::mono(tcx
, rust_main_def_id
).polymorphize(tcx
);
70 let main_name
= tcx
.symbol_name(instance
).name
;
71 let main_sig
= get_function_sig(tcx
, m
.isa().triple(), instance
);
72 let main_func_id
= m
.declare_function(main_name
, Linkage
::Import
, &main_sig
).unwrap();
74 let mut ctx
= Context
::new();
75 ctx
.func
= Function
::with_name_signature(ExternalName
::user(0, 0), cmain_sig
);
77 let mut func_ctx
= FunctionBuilderContext
::new();
78 let mut bcx
= FunctionBuilder
::new(&mut ctx
.func
, &mut func_ctx
);
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());
85 let main_func_ref
= m
.declare_func_in_func(main_func_id
, &mut bcx
.func
);
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();
93 let termination_trait
= tcx
.require_lang_item(LangItem
::Termination
, None
);
95 .associated_items(termination_trait
)
96 .find_by_name_and_kind(
98 Ident
::from_str("report"),
103 let report
= Instance
::resolve(
105 ParamEnv
::reveal_all(),
107 tcx
.mk_substs([GenericArg
::from(main_ret_ty
)].iter()),
112 let report_name
= tcx
.symbol_name(report
).name
;
113 let report_sig
= get_function_sig(tcx
, m
.isa().triple(), report
);
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
);
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() {
124 types
::I64
=> bcx
.ins().sextend(types
::I64
, res
),
125 _
=> unimplemented
!("16bit systems are not yet supported"),
127 } else if is_main_fn
{
128 let start_def_id
= tcx
.require_lang_item(LangItem
::Start
, None
);
129 let start_instance
= Instance
::resolve(
131 ParamEnv
::reveal_all(),
133 tcx
.intern_substs(&[main_ret_ty
.into()]),
138 let start_func_id
= import_function(tcx
, m
, start_instance
);
140 let main_val
= bcx
.ins().func_addr(m
.target_config().pointer_type(), main_func_ref
);
142 let func_ref
= m
.declare_func_in_func(start_func_id
, &mut bcx
.func
);
143 let call_inst
= bcx
.ins().call(func_ref
, &[main_val
, arg_argc
, arg_argv
]);
144 bcx
.inst_results(call_inst
)[0]
146 // using user-defined start fn
147 let call_inst
= bcx
.ins().call(main_func_ref
, &[arg_argc
, arg_argv
]);
148 bcx
.inst_results(call_inst
)[0]
151 bcx
.ins().return_(&[result
]);
152 bcx
.seal_all_blocks();
155 m
.define_function(cmain_func_id
, &mut ctx
, &mut NullTrapSink {}
, &mut NullStackMapSink {}
)
157 unwind_context
.add_function(cmain_func_id
, &ctx
, m
.isa());