@@ -63,14 +63,33 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
6363 }
6464}
6565
66+ enum PassMode {
67+ Direct ,
68+ Indirect ,
69+ }
70+
71+ enum SlotSize {
72+ Bytes8 = 8 ,
73+ Bytes4 = 4 ,
74+ }
75+
76+ enum AllowHigherAlign {
77+ No ,
78+ Yes ,
79+ }
80+
6681fn emit_ptr_va_arg < ' ll , ' tcx > (
6782 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
6883 list : OperandRef < ' tcx , & ' ll Value > ,
6984 target_ty : Ty < ' tcx > ,
70- indirect : bool ,
71- slot_size : Align ,
72- allow_higher_align : bool ,
85+ pass_mode : PassMode ,
86+ slot_size : SlotSize ,
87+ allow_higher_align : AllowHigherAlign ,
7388) -> & ' ll Value {
89+ let indirect = matches ! ( pass_mode, PassMode :: Indirect ) ;
90+ let allow_higher_align = matches ! ( allow_higher_align, AllowHigherAlign :: Yes ) ;
91+ let slot_size = Align :: from_bytes ( slot_size as u64 ) . unwrap ( ) ;
92+
7493 let layout = bx. cx . layout_of ( target_ty) ;
7594 let ( llty, size, align) = if indirect {
7695 (
@@ -179,8 +198,14 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
179198
180199 // On Stack block
181200 bx. switch_to_block ( on_stack) ;
182- let stack_value =
183- emit_ptr_va_arg ( bx, list, target_ty, false , Align :: from_bytes ( 8 ) . unwrap ( ) , true ) ;
201+ let stack_value = emit_ptr_va_arg (
202+ bx,
203+ list,
204+ target_ty,
205+ PassMode :: Direct ,
206+ SlotSize :: Bytes8 ,
207+ AllowHigherAlign :: Yes ,
208+ ) ;
184209 bx. br ( end) ;
185210
186211 bx. switch_to_block ( end) ;
@@ -386,29 +411,43 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
386411 // Determine the va_arg implementation to use. The LLVM va_arg instruction
387412 // is lacking in some instances, so we should only use it as a fallback.
388413 let target = & bx. cx . tcx . sess . target ;
389- let arch = & bx. cx . tcx . sess . target . arch ;
390- match & * * arch {
391- // Windows x86
392- "x86" if target. is_like_windows => {
393- emit_ptr_va_arg ( bx, addr, target_ty, false , Align :: from_bytes ( 4 ) . unwrap ( ) , false )
394- }
395- // Generic x86
396- "x86" => emit_ptr_va_arg ( bx, addr, target_ty, false , Align :: from_bytes ( 4 ) . unwrap ( ) , true ) ,
397- // Windows AArch64
398- "aarch64" | "arm64ec" if target. is_like_windows => {
399- emit_ptr_va_arg ( bx, addr, target_ty, false , Align :: from_bytes ( 8 ) . unwrap ( ) , false )
400- }
401- // macOS / iOS AArch64
402- "aarch64" if target. is_like_darwin => {
403- emit_ptr_va_arg ( bx, addr, target_ty, false , Align :: from_bytes ( 8 ) . unwrap ( ) , true )
414+
415+ match & * target. arch {
416+ "x86" => emit_ptr_va_arg (
417+ bx,
418+ addr,
419+ target_ty,
420+ PassMode :: Direct ,
421+ SlotSize :: Bytes4 ,
422+ if target. is_like_windows { AllowHigherAlign :: No } else { AllowHigherAlign :: Yes } ,
423+ ) ,
424+ "aarch64" | "arm64ec" if target. is_like_windows || target. is_like_darwin => {
425+ emit_ptr_va_arg (
426+ bx,
427+ addr,
428+ target_ty,
429+ PassMode :: Direct ,
430+ SlotSize :: Bytes8 ,
431+ if target. is_like_windows { AllowHigherAlign :: No } else { AllowHigherAlign :: Yes } ,
432+ )
404433 }
405434 "aarch64" => emit_aapcs_va_arg ( bx, addr, target_ty) ,
406435 "s390x" => emit_s390x_va_arg ( bx, addr, target_ty) ,
407436 // Windows x86_64
408437 "x86_64" if target. is_like_windows => {
409438 let target_ty_size = bx. cx . size_of ( target_ty) . bytes ( ) ;
410- let indirect: bool = target_ty_size > 8 || !target_ty_size. is_power_of_two ( ) ;
411- emit_ptr_va_arg ( bx, addr, target_ty, indirect, Align :: from_bytes ( 8 ) . unwrap ( ) , false )
439+ emit_ptr_va_arg (
440+ bx,
441+ addr,
442+ target_ty,
443+ if target_ty_size > 8 || !target_ty_size. is_power_of_two ( ) {
444+ PassMode :: Indirect
445+ } else {
446+ PassMode :: Direct
447+ } ,
448+ SlotSize :: Bytes8 ,
449+ AllowHigherAlign :: No ,
450+ )
412451 }
413452 "xtensa" => emit_xtensa_va_arg ( bx, addr, target_ty) ,
414453 // For all other architecture/OS combinations fall back to using
0 commit comments