1 use crate::abi::pass_mode::*;
4 fn return_layout<'a, 'tcx>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> TyLayout<'tcx> {
5 fx.layout_of(fx.monomorphize(&fx.mir.local_decls[RETURN_PLACE].ty))
8 pub(crate) fn can_return_to_ssa_var<'tcx>(tcx: TyCtxt<'tcx>, dest_layout: TyLayout<'tcx>) -> bool {
9 match get_pass_mode(tcx, dest_layout) {
10 PassMode::NoPass | PassMode::ByVal(_) => true,
11 // FIXME Make it possible to return ByValPair and ByRef to an ssa var.
12 PassMode::ByValPair(_, _) | PassMode::ByRef { sized: _ } => false
16 pub(super) fn codegen_return_param(
17 fx: &mut FunctionCx<impl Backend>,
18 ssa_analyzed: &rustc_index::vec::IndexVec<Local, crate::analyze::SsaKind>,
21 let ret_layout = return_layout(fx);
22 let ret_pass_mode = get_pass_mode(fx.tcx, ret_layout);
23 let ret_param = match ret_pass_mode {
26 .insert(RETURN_PLACE, CPlace::no_place(ret_layout));
29 PassMode::ByVal(_) | PassMode::ByValPair(_, _) => {
30 let is_ssa = ssa_analyzed[RETURN_PLACE] == crate::analyze::SsaKind::Ssa;
32 super::local_place(fx, RETURN_PLACE, ret_layout, is_ssa);
36 PassMode::ByRef { sized: true } => {
37 let ret_param = fx.bcx.append_block_param(start_block, fx.pointer_type);
39 .insert(RETURN_PLACE, CPlace::for_ptr(Pointer::new(ret_param), ret_layout));
43 PassMode::ByRef { sized: false } => todo!(),
46 #[cfg(not(debug_assertions))]
49 #[cfg(debug_assertions)]
50 crate::abi::comments::add_arg_comment(
61 pub(super) fn codegen_with_call_return_arg<'tcx, B: Backend, T>(
62 fx: &mut FunctionCx<'_, 'tcx, B>,
64 ret_place: Option<CPlace<'tcx>>,
65 f: impl FnOnce(&mut FunctionCx<'_, 'tcx, B>, Option<Value>) -> (Inst, T),
67 let ret_layout = fx.layout_of(fn_sig.output());
69 let output_pass_mode = get_pass_mode(fx.tcx, ret_layout);
70 let return_ptr = match output_pass_mode {
71 PassMode::NoPass => None,
72 PassMode::ByRef { sized: true } => match ret_place {
73 Some(ret_place) => Some(ret_place.to_ptr(fx).get_addr(fx)),
74 None => Some(fx.bcx.ins().iconst(fx.pointer_type, 43)),
76 PassMode::ByRef { sized: false } => todo!(),
77 PassMode::ByVal(_) | PassMode::ByValPair(_, _) => None,
80 let (call_inst, meta) = f(fx, return_ptr);
82 match output_pass_mode {
83 PassMode::NoPass => {}
84 PassMode::ByVal(_) => {
85 if let Some(ret_place) = ret_place {
86 let ret_val = fx.bcx.inst_results(call_inst)[0];
87 ret_place.write_cvalue(fx, CValue::by_val(ret_val, ret_layout));
90 PassMode::ByValPair(_, _) => {
91 if let Some(ret_place) = ret_place {
92 let ret_val_a = fx.bcx.inst_results(call_inst)[0];
93 let ret_val_b = fx.bcx.inst_results(call_inst)[1];
94 ret_place.write_cvalue(fx, CValue::by_val_pair(ret_val_a, ret_val_b, ret_layout));
97 PassMode::ByRef { sized: true } => {}
98 PassMode::ByRef { sized: false } => todo!(),
104 pub(crate) fn codegen_return(fx: &mut FunctionCx<impl Backend>) {
105 match get_pass_mode(fx.tcx, return_layout(fx)) {
106 PassMode::NoPass | PassMode::ByRef { sized: true } => {
107 fx.bcx.ins().return_(&[]);
109 PassMode::ByRef { sized: false } => todo!(),
110 PassMode::ByVal(_) => {
111 let place = fx.get_local_place(RETURN_PLACE);
112 let ret_val = place.to_cvalue(fx).load_scalar(fx);
113 fx.bcx.ins().return_(&[ret_val]);
115 PassMode::ByValPair(_, _) => {
116 let place = fx.get_local_place(RETURN_PLACE);
117 let (ret_val_a, ret_val_b) = place.to_cvalue(fx).load_scalar_pair(fx);
118 fx.bcx.ins().return_(&[ret_val_a, ret_val_b]);