Skip to content

Commit 1c516dc

Browse files
committed
c_variadic: provide va_arg for more targets
1 parent 08de25c commit 1c516dc

File tree

1 file changed

+81
-23
lines changed

1 file changed

+81
-23
lines changed

compiler/rustc_codegen_llvm/src/va_arg.rs

Lines changed: 81 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
use rustc_abi::{Align, BackendRepr, Endian, HasDataLayout, Primitive, Size, TyAndLayout};
1+
use rustc_abi::{Align, BackendRepr, Endian, HasDataLayout, Primitive, Size};
22
use rustc_codegen_ssa::MemFlags;
33
use rustc_codegen_ssa::common::IntPredicate;
44
use rustc_codegen_ssa::mir::operand::OperandRef;
55
use rustc_codegen_ssa::traits::{
66
BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, LayoutTypeCodegenMethods,
77
};
88
use rustc_middle::ty::Ty;
9-
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
9+
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
1010
use rustc_target::spec::{Abi, Arch};
1111

1212
use crate::builder::Builder;
@@ -82,6 +82,7 @@ enum PassMode {
8282
enum SlotSize {
8383
Bytes8 = 8,
8484
Bytes4 = 4,
85+
Bytes1 = 1,
8586
}
8687

8788
enum AllowHigherAlign {
@@ -726,7 +727,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
726727
fn 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>(
749750
fn 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.
881884
pub(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

Comments
 (0)