Set up arguments values `args` for a call with signature `sig`. This will return a series of instructions to be emitted to set up all arguments, as well as a `CallArgList` list representing the arguments passed in registers. The latter need to be added as constraints to the actual call instruction.
(
&self,
sigs: &SigSet,
sig: Sig,
args: &[ValueRegs<Reg>],
is_tail_call: bool,
flags: &settings::Flags,
vregs: &mut VRegAllocator<M::I>,
)
| 1788 | /// the arguments passed in registers. The latter need to be added |
| 1789 | /// as constraints to the actual call instruction. |
| 1790 | pub fn gen_call_args( |
| 1791 | &self, |
| 1792 | sigs: &SigSet, |
| 1793 | sig: Sig, |
| 1794 | args: &[ValueRegs<Reg>], |
| 1795 | is_tail_call: bool, |
| 1796 | flags: &settings::Flags, |
| 1797 | vregs: &mut VRegAllocator<M::I>, |
| 1798 | ) -> (CallArgList, SmallInstVec<M::I>) { |
| 1799 | let mut uses: CallArgList = smallvec![]; |
| 1800 | let mut insts = smallvec![]; |
| 1801 | |
| 1802 | assert_eq!(args.len(), sigs.num_args(sig)); |
| 1803 | |
| 1804 | let call_conv = sigs[sig].call_conv; |
| 1805 | let stack_arg_space = sigs[sig].sized_stack_arg_space; |
| 1806 | let stack_arg = |offset| { |
| 1807 | if is_tail_call { |
| 1808 | StackAMode::IncomingArg(offset, stack_arg_space) |
| 1809 | } else { |
| 1810 | StackAMode::OutgoingArg(offset) |
| 1811 | } |
| 1812 | }; |
| 1813 | |
| 1814 | let word_ty = M::word_type(); |
| 1815 | let word_rc = M::word_reg_class(); |
| 1816 | let word_bits = M::word_bits() as usize; |
| 1817 | |
| 1818 | if is_tail_call { |
| 1819 | debug_assert_eq!( |
| 1820 | self.call_conv, |
| 1821 | isa::CallConv::Tail, |
| 1822 | "Can only do `return_call`s from within a `tail` calling convention function" |
| 1823 | ); |
| 1824 | } |
| 1825 | |
| 1826 | // Helper to process a single argument slot (register or stack slot). |
| 1827 | // This will either add the register to the `uses` list or write the |
| 1828 | // value to the stack slot in the outgoing argument area (or for tail |
| 1829 | // calls, the incoming argument area). |
| 1830 | let mut process_arg_slot = |insts: &mut SmallInstVec<M::I>, slot, vreg, ty| { |
| 1831 | match &slot { |
| 1832 | &ABIArgSlot::Reg { reg, .. } => { |
| 1833 | uses.push(CallArgPair { |
| 1834 | vreg, |
| 1835 | preg: reg.into(), |
| 1836 | }); |
| 1837 | } |
| 1838 | &ABIArgSlot::Stack { offset, .. } => { |
| 1839 | insts.push(M::gen_store_stack(stack_arg(offset), vreg, ty)); |
| 1840 | } |
| 1841 | }; |
| 1842 | }; |
| 1843 | |
| 1844 | // First pass: Handle `StructArg` arguments. These need to be copied |
| 1845 | // into their associated stack buffers. This should happen before any |
| 1846 | // of the other arguments are processed, as the `memcpy` call might |
| 1847 | // clobber registers used by other arguments. |
no test coverage detected