2 use crate::abi::pass_mode::*;
4 pub fn codegen_return_param(
5 fx: &mut FunctionCx<impl Backend>,
6 ssa_analyzed: &HashMap<Local, crate::analyze::Flags>,
9 let ret_layout = fx.return_layout();
10 let output_pass_mode = get_pass_mode(fx.tcx, fx.return_layout());
12 let ret_param = match output_pass_mode {
15 .insert(RETURN_PLACE, CPlace::no_place(ret_layout));
18 PassMode::ByVal(_) | PassMode::ByValPair(_, _) => {
19 let is_ssa = !ssa_analyzed
22 .contains(crate::analyze::Flags::NOT_SSA);
24 super::local_place(fx, RETURN_PLACE, ret_layout, is_ssa);
29 let ret_param = fx.bcx.append_ebb_param(start_ebb, fx.pointer_type);
32 CPlace::for_addr(ret_param, ret_layout),
39 #[cfg(debug_assertions)]
41 super::add_arg_comment(
48 ssa_analyzed[&RETURN_PLACE],
54 pub fn codegen_with_call_return_arg<'tcx, B: Backend, T>(
55 fx: &mut FunctionCx<'_, 'tcx, B>,
57 ret_place: Option<CPlace<'tcx>>,
58 f: impl FnOnce(&mut FunctionCx<'_, 'tcx, B>, Option<Value>) -> (Inst, T),
60 let ret_layout = fx.layout_of(fn_sig.output());
62 let output_pass_mode = get_pass_mode(fx.tcx, ret_layout);
63 let return_ptr = match output_pass_mode {
64 PassMode::NoPass => None,
65 PassMode::ByRef => match ret_place {
66 Some(ret_place) => Some(ret_place.to_addr(fx)),
67 None => Some(fx.bcx.ins().iconst(fx.pointer_type, 43)),
69 PassMode::ByVal(_) | PassMode::ByValPair(_, _) => None,
72 let (call_inst, meta) = f(fx, return_ptr);
74 match output_pass_mode {
75 PassMode::NoPass => {}
76 PassMode::ByVal(_) => {
77 if let Some(ret_place) = ret_place {
78 let ret_val = fx.bcx.inst_results(call_inst)[0];
79 ret_place.write_cvalue(fx, CValue::by_val(ret_val, ret_layout));
82 PassMode::ByValPair(_, _) => {
83 if let Some(ret_place) = ret_place {
84 let ret_val_a = fx.bcx.inst_results(call_inst)[0];
85 let ret_val_b = fx.bcx.inst_results(call_inst)[1];
86 ret_place.write_cvalue(fx, CValue::by_val_pair(ret_val_a, ret_val_b, ret_layout));
95 pub fn codegen_return(fx: &mut FunctionCx<impl Backend>) {
96 match get_pass_mode(fx.tcx, fx.return_layout()) {
97 PassMode::NoPass | PassMode::ByRef => {
98 fx.bcx.ins().return_(&[]);
100 PassMode::ByVal(_) => {
101 let place = fx.get_local_place(RETURN_PLACE);
102 let ret_val = place.to_cvalue(fx).load_scalar(fx);
103 fx.bcx.ins().return_(&[ret_val]);
105 PassMode::ByValPair(_, _) => {
106 let place = fx.get_local_place(RETURN_PLACE);
107 let (ret_val_a, ret_val_b) = place.to_cvalue(fx).load_scalar_pair(fx);
108 fx.bcx.ins().return_(&[ret_val_a, ret_val_b]);