Skip to content

Commit 9d0af69

Browse files
committed
c_variadic: provide va_arg for more targets
1 parent 68f11a1 commit 9d0af69

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, Env};
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 {
@@ -728,7 +729,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
728729
fn copy_to_temporary_if_more_aligned<'ll, 'tcx>(
729730
bx: &mut Builder<'_, 'll, 'tcx>,
730731
reg_addr: &'ll Value,
731-
layout: TyAndLayout<'tcx, Ty<'tcx>>,
732+
layout: TyAndLayout<'tcx>,
732733
src_align: Align,
733734
) -> &'ll Value {
734735
if layout.layout.align.abi > src_align {
@@ -751,7 +752,7 @@ fn copy_to_temporary_if_more_aligned<'ll, 'tcx>(
751752
fn x86_64_sysv64_va_arg_from_memory<'ll, 'tcx>(
752753
bx: &mut Builder<'_, 'll, 'tcx>,
753754
va_list_addr: &'ll Value,
754-
layout: TyAndLayout<'tcx, Ty<'tcx>>,
755+
layout: TyAndLayout<'tcx>,
755756
) -> &'ll Value {
756757
let dl = bx.cx.data_layout();
757758
let ptr_align_abi = dl.data_layout().pointer_align().abi;
@@ -1003,15 +1004,17 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
10031004
return bx.load(layout.llvm_type(bx), value_ptr, layout.align.abi);
10041005
}
10051006

1007+
/// Determine the va_arg implementation to use. The LLVM va_arg instruction
1008+
/// is lacking in some instances, so we should only use it as a fallback.
10061009
pub(super) fn emit_va_arg<'ll, 'tcx>(
10071010
bx: &mut Builder<'_, 'll, 'tcx>,
10081011
addr: OperandRef<'tcx, &'ll Value>,
10091012
target_ty: Ty<'tcx>,
10101013
) -> &'ll Value {
1011-
// Determine the va_arg implementation to use. The LLVM va_arg instruction
1012-
// is lacking in some instances, so we should only use it as a fallback.
1013-
let target = &bx.cx.tcx.sess.target;
1014+
let layout = bx.cx.layout_of(target_ty);
1015+
let target_ty_size = layout.layout.size().bytes();
10141016

1017+
let target = &bx.cx.tcx.sess.target;
10151018
match target.arch {
10161019
Arch::X86 => emit_ptr_va_arg(
10171020
bx,
@@ -1069,23 +1072,78 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
10691072
AllowHigherAlign::Yes,
10701073
ForceRightAdjust::No,
10711074
),
1075+
Arch::LoongArch32 => emit_ptr_va_arg(
1076+
bx,
1077+
addr,
1078+
target_ty,
1079+
if target_ty_size > 2 * 4 { PassMode::Indirect } else { PassMode::Direct },
1080+
SlotSize::Bytes4,
1081+
AllowHigherAlign::Yes,
1082+
ForceRightAdjust::No,
1083+
),
1084+
Arch::LoongArch64 => emit_ptr_va_arg(
1085+
bx,
1086+
addr,
1087+
target_ty,
1088+
if target_ty_size > 2 * 8 { PassMode::Indirect } else { PassMode::Direct },
1089+
SlotSize::Bytes8,
1090+
AllowHigherAlign::Yes,
1091+
ForceRightAdjust::No,
1092+
),
1093+
Arch::AmdGpu => emit_ptr_va_arg(
1094+
bx,
1095+
addr,
1096+
target_ty,
1097+
PassMode::Direct,
1098+
SlotSize::Bytes4,
1099+
AllowHigherAlign::No,
1100+
ForceRightAdjust::No,
1101+
),
1102+
Arch::Nvptx64 => emit_ptr_va_arg(
1103+
bx,
1104+
addr,
1105+
target_ty,
1106+
PassMode::Direct,
1107+
SlotSize::Bytes1,
1108+
AllowHigherAlign::Yes,
1109+
ForceRightAdjust::No,
1110+
),
1111+
Arch::Wasm32 | Arch::Wasm64 => emit_ptr_va_arg(
1112+
bx,
1113+
addr,
1114+
target_ty,
1115+
if layout.is_aggregate() || layout.is_zst() || layout.is_1zst() {
1116+
PassMode::Indirect
1117+
} else {
1118+
PassMode::Direct
1119+
},
1120+
SlotSize::Bytes4,
1121+
AllowHigherAlign::Yes,
1122+
ForceRightAdjust::No,
1123+
),
1124+
Arch::CSky => emit_ptr_va_arg(
1125+
bx,
1126+
addr,
1127+
target_ty,
1128+
PassMode::Direct,
1129+
SlotSize::Bytes4,
1130+
AllowHigherAlign::Yes,
1131+
ForceRightAdjust::No,
1132+
),
10721133
// Windows x86_64
1073-
Arch::X86_64 if target.is_like_windows => {
1074-
let target_ty_size = bx.cx.size_of(target_ty).bytes();
1075-
emit_ptr_va_arg(
1076-
bx,
1077-
addr,
1078-
target_ty,
1079-
if target_ty_size > 8 || !target_ty_size.is_power_of_two() {
1080-
PassMode::Indirect
1081-
} else {
1082-
PassMode::Direct
1083-
},
1084-
SlotSize::Bytes8,
1085-
AllowHigherAlign::No,
1086-
ForceRightAdjust::No,
1087-
)
1088-
}
1134+
Arch::X86_64 if target.is_like_windows => emit_ptr_va_arg(
1135+
bx,
1136+
addr,
1137+
target_ty,
1138+
if target_ty_size > 8 || !target_ty_size.is_power_of_two() {
1139+
PassMode::Indirect
1140+
} else {
1141+
PassMode::Direct
1142+
},
1143+
SlotSize::Bytes8,
1144+
AllowHigherAlign::No,
1145+
ForceRightAdjust::No,
1146+
),
10891147
// This includes `target.is_like_darwin`, which on x86_64 targets is like sysv64.
10901148
Arch::X86_64 => emit_x86_64_sysv64_va_arg(bx, addr, target_ty),
10911149
Arch::Xtensa => emit_xtensa_va_arg(bx, addr, target_ty),

0 commit comments

Comments
 (0)