@@ -301,6 +301,14 @@ impl StackAMode {
301301 StackAMode :: SPOffset ( off, ty) => StackAMode :: SPOffset ( off + addend, ty) ,
302302 }
303303 }
304+
305+ pub fn get_type ( & self ) -> ir:: Type {
306+ match self {
307+ & StackAMode :: FPOffset ( _, ty) => ty,
308+ & StackAMode :: NominalSPOffset ( _, ty) => ty,
309+ & StackAMode :: SPOffset ( _, ty) => ty,
310+ }
311+ }
304312}
305313
306314/// Trait implemented by machine-specific backend to represent ISA flags.
@@ -2041,6 +2049,13 @@ impl<M: ABIMachineSpec> Callee<M> {
20412049 }
20422050}
20432051
2052+ /// The register or stack slot location of an argument.
2053+ #[ derive( Clone , Debug ) ]
2054+ pub enum ArgLoc {
2055+ Reg ( PReg ) ,
2056+ Stack ( StackAMode ) ,
2057+ }
2058+
20442059/// An input argument to a call instruction: the vreg that is used,
20452060/// and the preg it is constrained to (per the ABI).
20462061#[ derive( Clone , Debug ) ]
@@ -2289,6 +2304,20 @@ impl<M: ABIMachineSpec> CallSite<M> {
22892304 }
22902305 }
22912306
2307+ /// Emit moves or uses for the moves list generated by [`Self::gen_arg`].
2308+ pub fn emit_arg_moves ( & mut self , ctx : & mut Lower < M :: I > , moves : SmallVec < [ ( VReg , ArgLoc ) ; 2 ] > ) {
2309+ for ( vreg, loc) in moves {
2310+ let vreg = vreg. into ( ) ;
2311+ match loc {
2312+ ArgLoc :: Reg ( preg) => self . uses . push ( CallArgPair {
2313+ vreg,
2314+ preg : preg. into ( ) ,
2315+ } ) ,
2316+ ArgLoc :: Stack ( amode) => ctx. emit ( M :: gen_store_stack ( amode, vreg, amode. get_type ( ) ) ) ,
2317+ }
2318+ }
2319+ }
2320+
22922321 /// Add a constraint for an argument value from a source register.
22932322 /// For large arguments with associated stack buffer, this may
22942323 /// load the address of the buffer into the argument register, if
@@ -2298,8 +2327,9 @@ impl<M: ABIMachineSpec> CallSite<M> {
22982327 ctx : & mut Lower < M :: I > ,
22992328 idx : usize ,
23002329 from_regs : ValueRegs < Reg > ,
2301- ) -> SmallInstVec < M :: I > {
2302- let mut insts = smallvec ! [ ] ;
2330+ ) -> SmallVec < [ ( VReg , ArgLoc ) ; 2 ] > {
2331+ let mut insts = SmallInstVec :: new ( ) ;
2332+ let mut locs = smallvec ! [ ] ;
23032333 let word_rc = M :: word_reg_class ( ) ;
23042334 let word_bits = M :: word_bits ( ) as usize ;
23052335
@@ -2357,10 +2387,7 @@ impl<M: ABIMachineSpec> CallSite<M> {
23572387 ty_bits ( ty) as u8 ,
23582388 word_bits as u8 ,
23592389 ) ) ;
2360- self . uses . push ( CallArgPair {
2361- vreg : extend_result. to_reg ( ) ,
2362- preg : reg. into ( ) ,
2363- } ) ;
2390+ locs. push ( ( extend_result. to_reg ( ) . into ( ) , ArgLoc :: Reg ( reg. into ( ) ) ) ) ;
23642391 } else if ty. is_ref ( ) {
23652392 // Reference-typed args need to be
23662393 // passed as a copy; the original vreg
@@ -2369,15 +2396,10 @@ impl<M: ABIMachineSpec> CallSite<M> {
23692396 let ref_copy =
23702397 temps. pop ( ) . expect ( "Must have allocated enough temps" ) ;
23712398 insts. push ( M :: gen_move ( ref_copy, * from_reg, M :: word_type ( ) ) ) ;
2372- self . uses . push ( CallArgPair {
2373- vreg : ref_copy. to_reg ( ) ,
2374- preg : reg. into ( ) ,
2375- } ) ;
2399+
2400+ locs. push ( ( ref_copy. to_reg ( ) . into ( ) , ArgLoc :: Reg ( reg. into ( ) ) ) ) ;
23762401 } else {
2377- self . uses . push ( CallArgPair {
2378- vreg : * from_reg,
2379- preg : reg. into ( ) ,
2380- } ) ;
2402+ locs. push ( ( from_reg. into ( ) , ArgLoc :: Reg ( reg. into ( ) ) ) ) ;
23812403 }
23822404 }
23832405 & ABIArgSlot :: Stack {
@@ -2409,10 +2431,9 @@ impl<M: ABIMachineSpec> CallSite<M> {
24092431 } else {
24102432 ( * from_reg, ty)
24112433 } ;
2412- insts. push ( M :: gen_store_stack (
2413- StackAMode :: SPOffset ( offset, ty) ,
2414- data,
2415- ty,
2434+ locs. push ( (
2435+ data. into ( ) ,
2436+ ArgLoc :: Stack ( StackAMode :: SPOffset ( offset, ty) ) ,
24162437 ) ) ;
24172438 }
24182439 }
@@ -2434,25 +2455,22 @@ impl<M: ABIMachineSpec> CallSite<M> {
24342455 insts. push ( M :: gen_get_stack_addr ( amode, tmp, ty) ) ;
24352456 let tmp = tmp. to_reg ( ) ;
24362457 insts. push ( M :: gen_store_base_offset ( tmp, 0 , vreg, ty) ) ;
2437- match pointer {
2438- ABIArgSlot :: Reg { reg, .. } => {
2439- self . uses . push ( CallArgPair {
2440- vreg : tmp,
2441- preg : reg. into ( ) ,
2442- } ) ;
2443- }
2458+ let loc = match pointer {
2459+ ABIArgSlot :: Reg { reg, .. } => ArgLoc :: Reg ( reg. into ( ) ) ,
24442460 ABIArgSlot :: Stack { offset, .. } => {
24452461 let ty = M :: word_type ( ) ;
2446- insts. push ( M :: gen_store_stack (
2447- StackAMode :: SPOffset ( offset, ty) ,
2448- tmp,
2449- ty,
2450- ) ) ;
2462+ ArgLoc :: Stack ( StackAMode :: SPOffset ( offset, ty) )
24512463 }
24522464 } ;
2465+ locs. push ( ( tmp. into ( ) , loc) ) ;
24532466 }
24542467 }
2455- insts
2468+
2469+ for inst in insts {
2470+ ctx. emit ( inst) ;
2471+ }
2472+
2473+ locs
24562474 }
24572475
24582476 /// Call `gen_arg` for each non-hidden argument and emit all instructions
@@ -2470,9 +2488,8 @@ impl<M: ABIMachineSpec> CallSite<M> {
24702488 self . emit_copy_regs_to_buffer ( ctx, i, * arg_regs) ;
24712489 }
24722490 for ( i, value_regs) in arg_value_regs. iter ( ) . enumerate ( ) {
2473- for inst in self . gen_arg ( ctx, i, * value_regs) {
2474- ctx. emit ( inst) ;
2475- }
2491+ let moves = self . gen_arg ( ctx, i, * value_regs) ;
2492+ self . emit_arg_moves ( ctx, moves) ;
24762493 }
24772494 }
24782495
@@ -2484,9 +2501,8 @@ impl<M: ABIMachineSpec> CallSite<M> {
24842501 "if the tail callee has a return pointer, then the tail caller \
24852502 must as well",
24862503 ) ;
2487- for inst in self . gen_arg ( ctx, i. into ( ) , ValueRegs :: one ( ret_area_ptr. to_reg ( ) ) ) {
2488- ctx. emit ( inst) ;
2489- }
2504+ let moves = self . gen_arg ( ctx, i. into ( ) , ValueRegs :: one ( ret_area_ptr. to_reg ( ) ) ) ;
2505+ self . emit_arg_moves ( ctx, moves) ;
24902506 }
24912507 }
24922508
@@ -2592,9 +2608,8 @@ impl<M: ABIMachineSpec> CallSite<M> {
25922608 rd,
25932609 I8 ,
25942610 ) ) ;
2595- for inst in self . gen_arg ( ctx, i. into ( ) , ValueRegs :: one ( rd. to_reg ( ) ) ) {
2596- ctx. emit ( inst) ;
2597- }
2611+ let moves = self . gen_arg ( ctx, i. into ( ) , ValueRegs :: one ( rd. to_reg ( ) ) ) ;
2612+ self . emit_arg_moves ( ctx, moves) ;
25982613 }
25992614
26002615 let ( uses, defs) = (
0 commit comments