@@ -63,14 +63,33 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
63
63
}
64
64
}
65
65
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
+
66
81
fn emit_ptr_va_arg < ' ll , ' tcx > (
67
82
bx : & mut Builder < ' _ , ' ll , ' tcx > ,
68
83
list : OperandRef < ' tcx , & ' ll Value > ,
69
84
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 ,
73
88
) -> & ' 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
+
74
93
let layout = bx. cx . layout_of ( target_ty) ;
75
94
let ( llty, size, align) = if indirect {
76
95
(
@@ -179,8 +198,14 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
179
198
180
199
// On Stack block
181
200
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
+ ) ;
184
209
bx. br ( end) ;
185
210
186
211
bx. switch_to_block ( end) ;
@@ -386,29 +411,43 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
386
411
// Determine the va_arg implementation to use. The LLVM va_arg instruction
387
412
// is lacking in some instances, so we should only use it as a fallback.
388
413
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
+ )
404
433
}
405
434
"aarch64" => emit_aapcs_va_arg ( bx, addr, target_ty) ,
406
435
"s390x" => emit_s390x_va_arg ( bx, addr, target_ty) ,
407
436
// Windows x86_64
408
437
"x86_64" if target. is_like_windows => {
409
438
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
+ )
412
451
}
413
452
"xtensa" => emit_xtensa_va_arg ( bx, addr, target_ty) ,
414
453
// For all other architecture/OS combinations fall back to using
0 commit comments