|
2 | 2 |
|
3 | 3 | use crate::prelude::*;
|
4 | 4 |
|
| 5 | +use rustc_target::abi::call::{ArgAbi, ArgAttributes, PassMode as RustcPassMode}; |
5 | 6 | pub(super) use EmptySinglePair::*;
|
6 | 7 |
|
7 | 8 | #[derive(Copy, Clone, Debug)]
|
@@ -83,39 +84,64 @@ pub(super) fn get_pass_mode<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>)
|
83 | 84 | // WARNING zst arguments must never be passed, as that will break CastKind::ClosureFnPointer
|
84 | 85 | PassMode::NoPass
|
85 | 86 | } else {
|
86 |
| - match &layout.abi { |
87 |
| - Abi::Uninhabited => PassMode::NoPass, |
88 |
| - Abi::Scalar(scalar) => PassMode::ByVal(scalar_to_clif_type(tcx, scalar.clone())), |
89 |
| - Abi::ScalarPair(a, b) => { |
90 |
| - let a = scalar_to_clif_type(tcx, a.clone()); |
91 |
| - let b = scalar_to_clif_type(tcx, b.clone()); |
92 |
| - if a == types::I128 && b == types::I128 { |
93 |
| - // Returning (i128, i128) by-val-pair would take 4 regs, while only 3 are |
94 |
| - // available on x86_64. Cranelift gets confused when too many return params |
95 |
| - // are used. |
96 |
| - PassMode::ByRef { |
97 |
| - size: Some(layout.size), |
| 87 | + let arg_abi = ArgAbi::new(&tcx, layout, |_, _, _| ArgAttributes::new()); |
| 88 | + match arg_abi.mode { |
| 89 | + RustcPassMode::Ignore => PassMode::NoPass, |
| 90 | + RustcPassMode::Direct(_) => match &arg_abi.layout.abi { |
| 91 | + Abi::Scalar(scalar) => PassMode::ByVal(scalar_to_clif_type(tcx, scalar.clone())), |
| 92 | + // FIXME implement Vector Abi in a cg_llvm compatible way |
| 93 | + Abi::Vector { .. } => { |
| 94 | + if let Some(vector_ty) = crate::intrinsics::clif_vector_type(tcx, arg_abi.layout) { |
| 95 | + PassMode::ByVal(vector_ty) |
| 96 | + } else { |
| 97 | + PassMode::ByRef { |
| 98 | + size: Some(arg_abi.layout.size), |
| 99 | + } |
98 | 100 | }
|
99 |
| - } else { |
100 |
| - PassMode::ByValPair(a, b) |
101 | 101 | }
|
102 |
| - } |
103 |
| - |
104 |
| - // FIXME implement Vector Abi in a cg_llvm compatible way |
105 |
| - Abi::Vector { .. } => { |
106 |
| - if let Some(vector_ty) = crate::intrinsics::clif_vector_type(tcx, layout) { |
107 |
| - PassMode::ByVal(vector_ty) |
108 |
| - } else { |
109 |
| - PassMode::ByRef { |
110 |
| - size: Some(layout.size), |
| 102 | + _ => unreachable!("{:?}", arg_abi.layout.abi) |
| 103 | + }, |
| 104 | + RustcPassMode::Pair(_, _) => match &arg_abi.layout.abi { |
| 105 | + Abi::ScalarPair(a, b) => { |
| 106 | + let a = scalar_to_clif_type(tcx, a.clone()); |
| 107 | + let b = scalar_to_clif_type(tcx, b.clone()); |
| 108 | + if a == types::I128 && b == types::I128 { |
| 109 | + // Returning (i128, i128) by-val-pair would take 4 regs, while only 3 are |
| 110 | + // available on x86_64. Cranelift gets confused when too many return params |
| 111 | + // are used. |
| 112 | + PassMode::ByRef { |
| 113 | + size: Some(arg_abi.layout.size), |
| 114 | + } |
| 115 | + } else { |
| 116 | + PassMode::ByValPair(a, b) |
111 | 117 | }
|
112 | 118 | }
|
| 119 | + _ => unreachable!("{:?}", arg_abi.layout.abi) |
| 120 | + }, |
| 121 | + RustcPassMode::Cast(_) | RustcPassMode::Indirect { |
| 122 | + attrs: _, |
| 123 | + extra_attrs: None, |
| 124 | + on_stack: false, |
| 125 | + } => PassMode::ByRef { |
| 126 | + size: Some(arg_abi.layout.size), |
| 127 | + }, |
| 128 | + RustcPassMode::Indirect { |
| 129 | + attrs: _, |
| 130 | + extra_attrs, |
| 131 | + on_stack: true, |
| 132 | + } => { |
| 133 | + assert!(extra_attrs.is_none()); |
| 134 | + PassMode::ByRef { |
| 135 | + size: Some(arg_abi.layout.size) |
| 136 | + } |
113 | 137 | }
|
114 |
| - |
115 |
| - Abi::Aggregate { sized: true } => PassMode::ByRef { |
116 |
| - size: Some(layout.size), |
| 138 | + RustcPassMode::Indirect { |
| 139 | + attrs: _, |
| 140 | + extra_attrs: Some(_), |
| 141 | + on_stack: false, |
| 142 | + } => PassMode::ByRef { |
| 143 | + size: None, |
117 | 144 | },
|
118 |
| - Abi::Aggregate { sized: false } => PassMode::ByRef { size: None }, |
119 | 145 | }
|
120 | 146 | }
|
121 | 147 | }
|
|
0 commit comments