|
|
@ -643,114 +643,6 @@ pub struct SigData { |
|
|
|
} |
|
|
|
|
|
|
|
impl SigData { |
|
|
|
pub fn from_func_sig<M: ABIMachineSpec>( |
|
|
|
sigs: &mut SigSet, |
|
|
|
sig: &ir::Signature, |
|
|
|
flags: &settings::Flags, |
|
|
|
) -> CodegenResult<SigData> { |
|
|
|
let sret = missing_struct_return(sig); |
|
|
|
let returns = sret.as_ref().into_iter().chain(&sig.returns); |
|
|
|
|
|
|
|
// Compute args and retvals from signature. Handle retvals first,
|
|
|
|
// because we may need to add a return-area arg to the args.
|
|
|
|
let rets_start = u32::try_from(sigs.abi_args.len()).unwrap(); |
|
|
|
let (sized_stack_ret_space, _) = M::compute_arg_locs( |
|
|
|
sig.call_conv, |
|
|
|
flags, |
|
|
|
returns, |
|
|
|
ArgsOrRets::Rets, |
|
|
|
/* extra ret-area ptr = */ false, |
|
|
|
ArgsAccumulator::new(&mut sigs.abi_args), |
|
|
|
)?; |
|
|
|
let rets_end = u32::try_from(sigs.abi_args.len()).unwrap(); |
|
|
|
|
|
|
|
let need_stack_return_area = sized_stack_ret_space > 0; |
|
|
|
let args_start = u32::try_from(sigs.abi_args.len()).unwrap(); |
|
|
|
let (sized_stack_arg_space, stack_ret_arg) = M::compute_arg_locs( |
|
|
|
sig.call_conv, |
|
|
|
flags, |
|
|
|
&sig.params, |
|
|
|
ArgsOrRets::Args, |
|
|
|
need_stack_return_area, |
|
|
|
ArgsAccumulator::new(&mut sigs.abi_args), |
|
|
|
)?; |
|
|
|
let args_end = u32::try_from(sigs.abi_args.len()).unwrap(); |
|
|
|
|
|
|
|
let args_length = u16::try_from(args_end - args_start).unwrap(); |
|
|
|
let rets_length = u16::try_from(rets_end - rets_start).unwrap(); |
|
|
|
|
|
|
|
trace!( |
|
|
|
"ABISig: sig {:?} => args start = {} args len = {} rets start = {} rets len = {} |
|
|
|
arg stack = {} ret stack = {} stack_ret_arg = {:?}", |
|
|
|
sig, |
|
|
|
args_start, |
|
|
|
args_length, |
|
|
|
rets_start, |
|
|
|
rets_length, |
|
|
|
sized_stack_arg_space, |
|
|
|
sized_stack_ret_space, |
|
|
|
stack_ret_arg, |
|
|
|
); |
|
|
|
|
|
|
|
let stack_ret_arg = stack_ret_arg.map(|s| u16::try_from(s).unwrap()); |
|
|
|
Ok(SigData { |
|
|
|
args_start, |
|
|
|
args_length, |
|
|
|
rets_start, |
|
|
|
rets_length, |
|
|
|
sized_stack_arg_space, |
|
|
|
sized_stack_ret_space, |
|
|
|
stack_ret_arg, |
|
|
|
call_conv: sig.call_conv, |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
/// Get this signature's ABI arguments.
|
|
|
|
pub fn args<'a>(&self, sigs: &'a SigSet) -> &'a [ABIArg] { |
|
|
|
let start = usize::try_from(self.args_start).unwrap(); |
|
|
|
let end = usize::try_from(self.args_start + u32::from(self.args_length)).unwrap(); |
|
|
|
&sigs.abi_args[start..end] |
|
|
|
} |
|
|
|
|
|
|
|
/// Get this signature's ABI returns.
|
|
|
|
pub fn rets<'a>(&self, sigs: &'a SigSet) -> &'a [ABIArg] { |
|
|
|
let start = usize::try_from(self.rets_start).unwrap(); |
|
|
|
let end = usize::try_from(self.rets_start + u32::from(self.rets_length)).unwrap(); |
|
|
|
&sigs.abi_args[start..end] |
|
|
|
} |
|
|
|
|
|
|
|
/// Return all clobbers for the callsite.
|
|
|
|
pub fn call_clobbers<M: ABIMachineSpec>(&self, sigs: &SigSet) -> PRegSet { |
|
|
|
// Get clobbers: all caller-saves. These may include return value
|
|
|
|
// regs, which we will remove from the clobber set below.
|
|
|
|
let mut clobbers = M::get_regs_clobbered_by_call(self.call_conv); |
|
|
|
|
|
|
|
// Remove retval regs from clobbers. Skip StructRets: these
|
|
|
|
// are not, semantically, returns at the CLIF level, so we
|
|
|
|
// treat such a value as a clobber instead.
|
|
|
|
for ret in self.rets(sigs) { |
|
|
|
if let &ABIArg::Slots { |
|
|
|
ref slots, purpose, .. |
|
|
|
} = ret |
|
|
|
{ |
|
|
|
if purpose == ir::ArgumentPurpose::StructReturn { |
|
|
|
continue; |
|
|
|
} |
|
|
|
for slot in slots { |
|
|
|
match slot { |
|
|
|
&ABIArgSlot::Reg { reg, .. } => { |
|
|
|
log::trace!("call_clobbers: retval reg {:?}", reg); |
|
|
|
clobbers.remove(PReg::from(reg)); |
|
|
|
} |
|
|
|
_ => {} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
clobbers |
|
|
|
} |
|
|
|
|
|
|
|
/// Get the number of arguments expected.
|
|
|
|
pub fn num_args(&self) -> usize { |
|
|
|
let num = if self.stack_ret_arg.is_some() { |
|
|
@ -762,11 +654,6 @@ impl SigData { |
|
|
|
usize::from(num) |
|
|
|
} |
|
|
|
|
|
|
|
/// Get information specifying how to pass one argument.
|
|
|
|
pub fn get_arg(&self, sigs: &SigSet, idx: usize) -> ABIArg { |
|
|
|
self.args(sigs)[idx].clone() |
|
|
|
} |
|
|
|
|
|
|
|
/// Get total stack space required for arguments.
|
|
|
|
pub fn sized_stack_arg_space(&self) -> i64 { |
|
|
|
self.sized_stack_arg_space |
|
|
@ -777,23 +664,11 @@ impl SigData { |
|
|
|
usize::from(self.rets_length) |
|
|
|
} |
|
|
|
|
|
|
|
/// Get information specifying how to pass one return value.
|
|
|
|
pub fn get_ret(&self, sigs: &SigSet, idx: usize) -> ABIArg { |
|
|
|
self.rets(sigs)[idx].clone() |
|
|
|
} |
|
|
|
|
|
|
|
/// Get total stack space required for return values.
|
|
|
|
pub fn sized_stack_ret_space(&self) -> i64 { |
|
|
|
self.sized_stack_ret_space |
|
|
|
} |
|
|
|
|
|
|
|
/// Get information specifying how to pass the implicit pointer
|
|
|
|
/// to the return-value area on the stack, if required.
|
|
|
|
pub fn get_ret_arg(&self, sigs: &SigSet) -> Option<ABIArg> { |
|
|
|
let ret_arg = usize::from(self.stack_ret_arg?); |
|
|
|
Some(self.args(sigs)[ret_arg].clone()) |
|
|
|
} |
|
|
|
|
|
|
|
/// Get calling convention used.
|
|
|
|
pub fn call_conv(&self) -> isa::CallConv { |
|
|
|
self.call_conv |
|
|
@ -878,7 +753,7 @@ impl SigSet { |
|
|
|
// `ir::Signature`.
|
|
|
|
debug_assert!(!self.have_abi_sig_for_signature(&signature)); |
|
|
|
|
|
|
|
let sig_data = SigData::from_func_sig::<M>(self, &signature, flags)?; |
|
|
|
let sig_data = self.from_func_sig::<M>(&signature, flags)?; |
|
|
|
let sig = self.sigs.push(sig_data); |
|
|
|
self.ir_signature_to_abi_sig.insert(signature, sig); |
|
|
|
Ok(sig) |
|
|
@ -897,7 +772,7 @@ impl SigSet { |
|
|
|
return Ok(sig); |
|
|
|
} |
|
|
|
let signature = &dfg.signatures[sig_ref]; |
|
|
|
let sig_data = SigData::from_func_sig::<M>(self, signature, flags)?; |
|
|
|
let sig_data = self.from_func_sig::<M>(signature, flags)?; |
|
|
|
let sig = self.sigs.push(sig_data); |
|
|
|
self.ir_sig_ref_to_abi_sig[sig_ref] = Some(sig); |
|
|
|
Ok(sig) |
|
|
@ -920,6 +795,138 @@ impl SigSet { |
|
|
|
.copied() |
|
|
|
.expect("must call `make_abi_sig_from_ir_signature` before `get_abi_sig_for_signature`") |
|
|
|
} |
|
|
|
|
|
|
|
pub fn from_func_sig<M: ABIMachineSpec>( |
|
|
|
&mut self, |
|
|
|
sig: &ir::Signature, |
|
|
|
flags: &settings::Flags, |
|
|
|
) -> CodegenResult<SigData> { |
|
|
|
let sret = missing_struct_return(sig); |
|
|
|
let returns = sret.as_ref().into_iter().chain(&sig.returns); |
|
|
|
|
|
|
|
// Compute args and retvals from signature. Handle retvals first,
|
|
|
|
// because we may need to add a return-area arg to the args.
|
|
|
|
let rets_start = u32::try_from(self.abi_args.len()).unwrap(); |
|
|
|
let (sized_stack_ret_space, _) = M::compute_arg_locs( |
|
|
|
sig.call_conv, |
|
|
|
flags, |
|
|
|
returns, |
|
|
|
ArgsOrRets::Rets, |
|
|
|
/* extra ret-area ptr = */ false, |
|
|
|
ArgsAccumulator::new(&mut self.abi_args), |
|
|
|
)?; |
|
|
|
let rets_end = u32::try_from(self.abi_args.len()).unwrap(); |
|
|
|
|
|
|
|
let need_stack_return_area = sized_stack_ret_space > 0; |
|
|
|
let args_start = u32::try_from(self.abi_args.len()).unwrap(); |
|
|
|
let (sized_stack_arg_space, stack_ret_arg) = M::compute_arg_locs( |
|
|
|
sig.call_conv, |
|
|
|
flags, |
|
|
|
&sig.params, |
|
|
|
ArgsOrRets::Args, |
|
|
|
need_stack_return_area, |
|
|
|
ArgsAccumulator::new(&mut self.abi_args), |
|
|
|
)?; |
|
|
|
let args_end = u32::try_from(self.abi_args.len()).unwrap(); |
|
|
|
|
|
|
|
let args_length = u16::try_from(args_end - args_start).unwrap(); |
|
|
|
let rets_length = u16::try_from(rets_end - rets_start).unwrap(); |
|
|
|
|
|
|
|
trace!( |
|
|
|
"ABISig: sig {:?} => args start = {} args len = {} rets start = {} rets len = {} |
|
|
|
arg stack = {} ret stack = {} stack_ret_arg = {:?}", |
|
|
|
sig, |
|
|
|
args_start, |
|
|
|
args_length, |
|
|
|
rets_start, |
|
|
|
rets_length, |
|
|
|
sized_stack_arg_space, |
|
|
|
sized_stack_ret_space, |
|
|
|
need_stack_return_area, |
|
|
|
); |
|
|
|
|
|
|
|
let stack_ret_arg = stack_ret_arg.map(|s| u16::try_from(s).unwrap()); |
|
|
|
Ok(SigData { |
|
|
|
args_start, |
|
|
|
args_length, |
|
|
|
rets_start, |
|
|
|
rets_length, |
|
|
|
sized_stack_arg_space, |
|
|
|
sized_stack_ret_space, |
|
|
|
stack_ret_arg, |
|
|
|
call_conv: sig.call_conv, |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
/// Get this signature's ABI arguments.
|
|
|
|
pub fn args(&self, sig: Sig) -> &[ABIArg] { |
|
|
|
let sig_data = &self.sigs[sig]; |
|
|
|
let start = usize::try_from(sig_data.args_start).unwrap(); |
|
|
|
let end = usize::try_from(sig_data.args_start + u32::from(sig_data.args_length)).unwrap(); |
|
|
|
&self.abi_args[start..end] |
|
|
|
} |
|
|
|
|
|
|
|
/// Get information specifying how to pass the implicit pointer
|
|
|
|
/// to the return-value area on the stack, if required.
|
|
|
|
pub fn get_ret_arg(&self, sig: Sig) -> Option<ABIArg> { |
|
|
|
let sig_data = &self.sigs[sig]; |
|
|
|
if let Some(i) = sig_data.stack_ret_arg { |
|
|
|
Some(self.args(sig)[usize::from(i)].clone()) |
|
|
|
} else { |
|
|
|
None |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// Get information specifying how to pass one argument.
|
|
|
|
pub fn get_arg(&self, sig: Sig, idx: usize) -> ABIArg { |
|
|
|
self.args(sig)[idx].clone() |
|
|
|
} |
|
|
|
|
|
|
|
/// Get this signature's ABI returns.
|
|
|
|
pub fn rets(&self, sig: Sig) -> &[ABIArg] { |
|
|
|
let sig_data = &self.sigs[sig]; |
|
|
|
let start = usize::try_from(sig_data.rets_start).unwrap(); |
|
|
|
let end = usize::try_from(sig_data.rets_start + u32::from(sig_data.rets_length)).unwrap(); |
|
|
|
&self.abi_args[start..end] |
|
|
|
} |
|
|
|
|
|
|
|
/// Get information specifying how to pass one return value.
|
|
|
|
pub fn get_ret(&self, sig: Sig, idx: usize) -> ABIArg { |
|
|
|
self.rets(sig)[idx].clone() |
|
|
|
} |
|
|
|
|
|
|
|
/// Return all clobbers for the callsite.
|
|
|
|
pub fn call_clobbers<M: ABIMachineSpec>(&self, sig: Sig) -> PRegSet { |
|
|
|
let sig_data = &self.sigs[sig]; |
|
|
|
// Get clobbers: all caller-saves. These may include return value
|
|
|
|
// regs, which we will remove from the clobber set below.
|
|
|
|
let mut clobbers = M::get_regs_clobbered_by_call(sig_data.call_conv); |
|
|
|
|
|
|
|
// Remove retval regs from clobbers. Skip StructRets: these
|
|
|
|
// are not, semantically, returns at the CLIF level, so we
|
|
|
|
// treat such a value as a clobber instead.
|
|
|
|
for ret in self.rets(sig) { |
|
|
|
if let &ABIArg::Slots { |
|
|
|
ref slots, purpose, .. |
|
|
|
} = ret |
|
|
|
{ |
|
|
|
if purpose == ir::ArgumentPurpose::StructReturn { |
|
|
|
continue; |
|
|
|
} |
|
|
|
for slot in slots { |
|
|
|
match slot { |
|
|
|
&ABIArgSlot::Reg { reg, .. } => { |
|
|
|
log::trace!("call_clobbers: retval reg {:?}", reg); |
|
|
|
clobbers.remove(PReg::from(reg)); |
|
|
|
} |
|
|
|
_ => {} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
clobbers |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// NB: we do _not_ implement `IndexMut` because these signatures are
|
|
|
@ -999,11 +1006,11 @@ pub struct Callee<M: ABIMachineSpec> { |
|
|
|
fn get_special_purpose_param_register( |
|
|
|
f: &ir::Function, |
|
|
|
sigs: &SigSet, |
|
|
|
abi: &SigData, |
|
|
|
sig: &Sig, |
|
|
|
purpose: ir::ArgumentPurpose, |
|
|
|
) -> Option<Reg> { |
|
|
|
let idx = f.signature.special_param_index(purpose)?; |
|
|
|
match &abi.args(sigs)[idx] { |
|
|
|
match &sigs.args(*sig)[idx] { |
|
|
|
&ABIArg::Slots { ref slots, .. } => match &slots[0] { |
|
|
|
&ABIArgSlot::Reg { reg, .. } => Some(reg.into()), |
|
|
|
_ => None, |
|
|
@ -1080,16 +1087,12 @@ impl<M: ABIMachineSpec> Callee<M> { |
|
|
|
// stack limit. This can either be specified as a special-purpose
|
|
|
|
// argument or as a global value which often calculates the stack limit
|
|
|
|
// from the arguments.
|
|
|
|
let stack_limit = get_special_purpose_param_register( |
|
|
|
f, |
|
|
|
sigs, |
|
|
|
&sigs[sig], |
|
|
|
ir::ArgumentPurpose::StackLimit, |
|
|
|
) |
|
|
|
let stack_limit = |
|
|
|
get_special_purpose_param_register(f, sigs, &sig, ir::ArgumentPurpose::StackLimit) |
|
|
|
.map(|reg| (reg, smallvec![])) |
|
|
|
.or_else(|| { |
|
|
|
f.stack_limit |
|
|
|
.map(|gv| gen_stack_limit::<M>(f, sigs, &sigs[sig], gv)) |
|
|
|
.map(|gv| gen_stack_limit::<M>(f, sigs, &sig, gv)) |
|
|
|
}); |
|
|
|
|
|
|
|
// Determine whether a probestack call is required for large enough
|
|
|
@ -1210,25 +1213,25 @@ impl<M: ABIMachineSpec> Callee<M> { |
|
|
|
fn gen_stack_limit<M: ABIMachineSpec>( |
|
|
|
f: &ir::Function, |
|
|
|
sigs: &SigSet, |
|
|
|
abi: &SigData, |
|
|
|
sig: &Sig, |
|
|
|
gv: ir::GlobalValue, |
|
|
|
) -> (Reg, SmallInstVec<M::I>) { |
|
|
|
let mut insts = smallvec![]; |
|
|
|
let reg = generate_gv::<M>(f, sigs, abi, gv, &mut insts); |
|
|
|
let reg = generate_gv::<M>(f, sigs, sig, gv, &mut insts); |
|
|
|
return (reg, insts); |
|
|
|
} |
|
|
|
|
|
|
|
fn generate_gv<M: ABIMachineSpec>( |
|
|
|
f: &ir::Function, |
|
|
|
sigs: &SigSet, |
|
|
|
abi: &SigData, |
|
|
|
sig: &Sig, |
|
|
|
gv: ir::GlobalValue, |
|
|
|
insts: &mut SmallInstVec<M::I>, |
|
|
|
) -> Reg { |
|
|
|
match f.global_values[gv] { |
|
|
|
// Return the direct register the vmcontext is in
|
|
|
|
ir::GlobalValueData::VMContext => { |
|
|
|
get_special_purpose_param_register(f, sigs, abi, ir::ArgumentPurpose::VMContext) |
|
|
|
get_special_purpose_param_register(f, sigs, sig, ir::ArgumentPurpose::VMContext) |
|
|
|
.expect("no vmcontext parameter found") |
|
|
|
} |
|
|
|
// Load our base value into a register, then load from that register
|
|
|
@ -1239,7 +1242,7 @@ fn generate_gv<M: ABIMachineSpec>( |
|
|
|
global_type: _, |
|
|
|
readonly: _, |
|
|
|
} => { |
|
|
|
let base = generate_gv::<M>(f, sigs, abi, base, insts); |
|
|
|
let base = generate_gv::<M>(f, sigs, sig, base, insts); |
|
|
|
let into_reg = Writable::from_reg(M::get_stacklimit_reg()); |
|
|
|
insts.push(M::gen_load_base_offset( |
|
|
|
into_reg, |
|
|
@ -1321,7 +1324,7 @@ impl<M: ABIMachineSpec> Callee<M> { |
|
|
|
/// They will be provided to `init()` as the `temps` arg if so.
|
|
|
|
pub fn temps_needed(&self, sigs: &SigSet) -> Vec<Type> { |
|
|
|
let mut temp_tys = vec![]; |
|
|
|
for arg in sigs[self.sig].args(sigs) { |
|
|
|
for arg in sigs.args(self.sig) { |
|
|
|
match arg { |
|
|
|
&ABIArg::ImplicitPtrArg { pointer, .. } => match &pointer { |
|
|
|
&ABIArgSlot::Reg { .. } => {} |
|
|
@ -1343,7 +1346,7 @@ impl<M: ABIMachineSpec> Callee<M> { |
|
|
|
/// once the lowering context exists.
|
|
|
|
pub fn init(&mut self, sigs: &SigSet, temps: Vec<Writable<Reg>>) { |
|
|
|
let mut temps_iter = temps.into_iter(); |
|
|
|
for arg in sigs[self.sig].args(sigs) { |
|
|
|
for arg in sigs.args(self.sig) { |
|
|
|
let temp = match arg { |
|
|
|
&ABIArg::ImplicitPtrArg { pointer, .. } => match &pointer { |
|
|
|
&ABIArgSlot::Reg { .. } => None, |
|
|
@ -1441,7 +1444,7 @@ impl<M: ABIMachineSpec> Callee<M> { |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
match &sigs[self.sig].args(sigs)[idx] { |
|
|
|
match &sigs.args(self.sig)[idx] { |
|
|
|
&ABIArg::Slots { ref slots, .. } => { |
|
|
|
assert_eq!(into_regs.len(), slots.len()); |
|
|
|
for (slot, into_reg) in slots.iter().zip(into_regs.regs().iter()) { |
|
|
@ -1518,7 +1521,7 @@ impl<M: ABIMachineSpec> Callee<M> { |
|
|
|
let mut reg_pairs = smallvec![]; |
|
|
|
let mut ret = smallvec![]; |
|
|
|
let word_bits = M::word_bits() as u8; |
|
|
|
match &sigs[self.sig].rets(sigs)[idx] { |
|
|
|
match &sigs.rets(self.sig)[idx] { |
|
|
|
&ABIArg::Slots { ref slots, .. } => { |
|
|
|
assert_eq!(from_regs.len(), slots.len()); |
|
|
|
for (slot, &from_reg) in slots.iter().zip(from_regs.regs().iter()) { |
|
|
@ -2015,7 +2018,7 @@ impl<M: ABIMachineSpec> Caller<M> { |
|
|
|
flags: settings::Flags, |
|
|
|
) -> CodegenResult<Caller<M>> { |
|
|
|
let sig = sigs.abi_sig_for_sig_ref(sig_ref); |
|
|
|
let clobbers = sigs[sig].call_clobbers::<M>(sigs); |
|
|
|
let clobbers = sigs.call_clobbers::<M>(sig); |
|
|
|
Ok(Caller { |
|
|
|
sig, |
|
|
|
uses: smallvec![], |
|
|
@ -2040,7 +2043,7 @@ impl<M: ABIMachineSpec> Caller<M> { |
|
|
|
flags: settings::Flags, |
|
|
|
) -> CodegenResult<Caller<M>> { |
|
|
|
let sig = sigs.abi_sig_for_signature(sig); |
|
|
|
let clobbers = sigs[sig].call_clobbers::<M>(sigs); |
|
|
|
let clobbers = sigs.call_clobbers::<M>(sig); |
|
|
|
Ok(Caller { |
|
|
|
sig, |
|
|
|
uses: smallvec![], |
|
|
@ -2065,7 +2068,7 @@ impl<M: ABIMachineSpec> Caller<M> { |
|
|
|
flags: settings::Flags, |
|
|
|
) -> CodegenResult<Caller<M>> { |
|
|
|
let sig = sigs.abi_sig_for_sig_ref(sig_ref); |
|
|
|
let clobbers = sigs[sig].call_clobbers::<M>(sigs); |
|
|
|
let clobbers = sigs.call_clobbers::<M>(sig); |
|
|
|
Ok(Caller { |
|
|
|
sig, |
|
|
|
uses: smallvec![], |
|
|
@ -2094,9 +2097,8 @@ fn adjust_stack_and_nominal_sp<M: ABIMachineSpec>(ctx: &mut Lower<M::I>, off: i3 |
|
|
|
impl<M: ABIMachineSpec> Caller<M> { |
|
|
|
/// Get the number of arguments expected.
|
|
|
|
pub fn num_args(&self, sigs: &SigSet) -> usize { |
|
|
|
let data = &sigs[self.sig]; |
|
|
|
let len = data.args(sigs).len(); |
|
|
|
if data.stack_ret_arg.is_some() { |
|
|
|
let len = sigs.args(self.sig).len(); |
|
|
|
if sigs[self.sig].stack_ret_arg.is_some() { |
|
|
|
len - 1 |
|
|
|
} else { |
|
|
|
len |
|
|
@ -2128,7 +2130,7 @@ impl<M: ABIMachineSpec> Caller<M> { |
|
|
|
idx: usize, |
|
|
|
from_regs: ValueRegs<Reg>, |
|
|
|
) { |
|
|
|
match &ctx.sigs()[self.sig].args(ctx.sigs())[idx] { |
|
|
|
match &ctx.sigs().args(self.sig)[idx] { |
|
|
|
&ABIArg::Slots { .. } => {} |
|
|
|
&ABIArg::StructArg { offset, size, .. } => { |
|
|
|
let src_ptr = from_regs.only_reg().unwrap(); |
|
|
@ -2180,7 +2182,7 @@ impl<M: ABIMachineSpec> Caller<M> { |
|
|
|
// How many temps do we need for extends? Allocate them ahead
|
|
|
|
// of time, since we can't do it while we're iterating over
|
|
|
|
// the sig and immutably borrowing `ctx`.
|
|
|
|
let needed_tmps = match &ctx.sigs()[self.sig].args(ctx.sigs())[idx] { |
|
|
|
let needed_tmps = match &ctx.sigs().args(self.sig)[idx] { |
|
|
|
&ABIArg::Slots { ref slots, .. } => slots |
|
|
|
.iter() |
|
|
|
.map(|slot| match slot { |
|
|
@ -2205,7 +2207,7 @@ impl<M: ABIMachineSpec> Caller<M> { |
|
|
|
.map(|_| ctx.alloc_tmp(M::word_type()).only_reg().unwrap()) |
|
|
|
.collect(); |
|
|
|
|
|
|
|
match &ctx.sigs()[self.sig].args(ctx.sigs())[idx] { |
|
|
|
match &ctx.sigs().args(self.sig)[idx] { |
|
|
|
&ABIArg::Slots { ref slots, .. } => { |
|
|
|
assert_eq!(from_regs.len(), slots.len()); |
|
|
|
for (slot, from_reg) in slots.iter().zip(from_regs.regs().iter()) { |
|
|
@ -2307,7 +2309,7 @@ impl<M: ABIMachineSpec> Caller<M> { |
|
|
|
into_regs: ValueRegs<Writable<Reg>>, |
|
|
|
) -> SmallInstVec<M::I> { |
|
|
|
let mut insts = smallvec![]; |
|
|
|
match &ctx.sigs()[self.sig].rets(ctx.sigs())[idx] { |
|
|
|
match &ctx.sigs().rets(self.sig)[idx] { |
|
|
|
&ABIArg::Slots { ref slots, .. } => { |
|
|
|
assert_eq!(into_regs.len(), slots.len()); |
|
|
|
for (slot, into_reg) in slots.iter().zip(into_regs.regs().iter()) { |
|
|
|