1- use rustc_abi:: { Align , BackendRepr , Endian , HasDataLayout , Primitive , Size , TyAndLayout } ;
1+ use rustc_abi:: { Align , BackendRepr , Endian , HasDataLayout , Primitive , Size } ;
22use rustc_codegen_ssa:: MemFlags ;
33use rustc_codegen_ssa:: common:: IntPredicate ;
44use rustc_codegen_ssa:: mir:: operand:: OperandRef ;
55use rustc_codegen_ssa:: traits:: {
66 BaseTypeCodegenMethods , BuilderMethods , ConstCodegenMethods , LayoutTypeCodegenMethods ,
77} ;
88use rustc_middle:: ty:: Ty ;
9- use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf } ;
9+ use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , TyAndLayout } ;
1010use rustc_target:: spec:: { Abi , Arch } ;
1111
1212use crate :: builder:: Builder ;
@@ -82,6 +82,7 @@ enum PassMode {
8282enum SlotSize {
8383 Bytes8 = 8 ,
8484 Bytes4 = 4 ,
85+ Bytes1 = 1 ,
8586}
8687
8788enum AllowHigherAlign {
@@ -726,7 +727,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
726727fn copy_to_temporary_if_more_aligned < ' ll , ' tcx > (
727728 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
728729 reg_addr : & ' ll Value ,
729- layout : TyAndLayout < ' tcx , Ty < ' tcx > > ,
730+ layout : TyAndLayout < ' tcx > ,
730731 src_align : Align ,
731732) -> & ' ll Value {
732733 if layout. layout . align . abi > src_align {
@@ -749,7 +750,7 @@ fn copy_to_temporary_if_more_aligned<'ll, 'tcx>(
749750fn x86_64_sysv64_va_arg_from_memory < ' ll , ' tcx > (
750751 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
751752 va_list_addr : & ' ll Value ,
752- layout : TyAndLayout < ' tcx , Ty < ' tcx > > ,
753+ layout : TyAndLayout < ' tcx > ,
753754) -> & ' ll Value {
754755 let dl = bx. cx . data_layout ( ) ;
755756 let ptr_align_abi = dl. data_layout ( ) . pointer_align ( ) . abi ;
@@ -878,15 +879,17 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
878879 return bx. load ( layout. llvm_type ( bx) , value_ptr, layout. align . abi ) ;
879880}
880881
882+ /// Determine the va_arg implementation to use. The LLVM va_arg instruction
883+ /// is lacking in some instances, so we should only use it as a fallback.
881884pub ( super ) fn emit_va_arg < ' ll , ' tcx > (
882885 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
883886 addr : OperandRef < ' tcx , & ' ll Value > ,
884887 target_ty : Ty < ' tcx > ,
885888) -> & ' ll Value {
886- // Determine the va_arg implementation to use. The LLVM va_arg instruction
887- // is lacking in some instances, so we should only use it as a fallback.
888- let target = & bx. cx . tcx . sess . target ;
889+ let layout = bx. cx . layout_of ( target_ty) ;
890+ let target_ty_size = layout. layout . size ( ) . bytes ( ) ;
889891
892+ let target = & bx. cx . tcx . sess . target ;
890893 match target. arch {
891894 Arch :: X86 => emit_ptr_va_arg (
892895 bx,
@@ -944,23 +947,78 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
944947 AllowHigherAlign :: Yes ,
945948 ForceRightAdjust :: No ,
946949 ) ,
950+ Arch :: LoongArch32 => emit_ptr_va_arg (
951+ bx,
952+ addr,
953+ target_ty,
954+ if target_ty_size > 2 * 4 { PassMode :: Indirect } else { PassMode :: Direct } ,
955+ SlotSize :: Bytes4 ,
956+ AllowHigherAlign :: Yes ,
957+ ForceRightAdjust :: No ,
958+ ) ,
959+ Arch :: LoongArch64 => emit_ptr_va_arg (
960+ bx,
961+ addr,
962+ target_ty,
963+ if target_ty_size > 2 * 8 { PassMode :: Indirect } else { PassMode :: Direct } ,
964+ SlotSize :: Bytes8 ,
965+ AllowHigherAlign :: Yes ,
966+ ForceRightAdjust :: No ,
967+ ) ,
968+ Arch :: AmdGpu => emit_ptr_va_arg (
969+ bx,
970+ addr,
971+ target_ty,
972+ PassMode :: Direct ,
973+ SlotSize :: Bytes4 ,
974+ AllowHigherAlign :: No ,
975+ ForceRightAdjust :: No ,
976+ ) ,
977+ Arch :: Nvptx64 => emit_ptr_va_arg (
978+ bx,
979+ addr,
980+ target_ty,
981+ PassMode :: Direct ,
982+ SlotSize :: Bytes1 ,
983+ AllowHigherAlign :: Yes ,
984+ ForceRightAdjust :: No ,
985+ ) ,
986+ Arch :: Wasm32 | Arch :: Wasm64 => emit_ptr_va_arg (
987+ bx,
988+ addr,
989+ target_ty,
990+ if layout. is_aggregate ( ) || layout. is_zst ( ) || layout. is_1zst ( ) {
991+ PassMode :: Indirect
992+ } else {
993+ PassMode :: Direct
994+ } ,
995+ SlotSize :: Bytes4 ,
996+ AllowHigherAlign :: Yes ,
997+ ForceRightAdjust :: No ,
998+ ) ,
999+ Arch :: CSky => emit_ptr_va_arg (
1000+ bx,
1001+ addr,
1002+ target_ty,
1003+ PassMode :: Direct ,
1004+ SlotSize :: Bytes4 ,
1005+ AllowHigherAlign :: Yes ,
1006+ ForceRightAdjust :: No ,
1007+ ) ,
9471008 // Windows x86_64
948- Arch :: X86_64 if target. is_like_windows => {
949- let target_ty_size = bx. cx . size_of ( target_ty) . bytes ( ) ;
950- emit_ptr_va_arg (
951- bx,
952- addr,
953- target_ty,
954- if target_ty_size > 8 || !target_ty_size. is_power_of_two ( ) {
955- PassMode :: Indirect
956- } else {
957- PassMode :: Direct
958- } ,
959- SlotSize :: Bytes8 ,
960- AllowHigherAlign :: No ,
961- ForceRightAdjust :: No ,
962- )
963- }
1009+ Arch :: X86_64 if target. is_like_windows => emit_ptr_va_arg (
1010+ bx,
1011+ addr,
1012+ target_ty,
1013+ if target_ty_size > 8 || !target_ty_size. is_power_of_two ( ) {
1014+ PassMode :: Indirect
1015+ } else {
1016+ PassMode :: Direct
1017+ } ,
1018+ SlotSize :: Bytes8 ,
1019+ AllowHigherAlign :: No ,
1020+ ForceRightAdjust :: No ,
1021+ ) ,
9641022 // This includes `target.is_like_darwin`, which on x86_64 targets is like sysv64.
9651023 Arch :: X86_64 => emit_x86_64_sysv64_va_arg ( bx, addr, target_ty) ,
9661024 Arch :: Xtensa => emit_xtensa_va_arg ( bx, addr, target_ty) ,
0 commit comments