Skip to content

Commit cf9293c

Browse files
authored
Unrolled build for #152576
Rollup merge of #152576 - folkertdev:mips-va-arg, r=tgross35 c-variadic: use `emit_ptr_va_arg` for mips tracking issue: #44930 After reading the implementation carefully, I believe it really is just `emit_ptr_va_arg`. The LLVM implementation can be found here: https://github.com/llvm/llvm-project/blob/289a3292be0c6a3df86bcdf5be7dd05b79a5570c/llvm/lib/Target/Mips/MipsISelLowering.cpp#L2338. r? workingjubilee
2 parents 92c7010 + e9ab558 commit cf9293c

2 files changed

Lines changed: 156 additions & 4 deletions

File tree

compiler/rustc_codegen_llvm/src/va_arg.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,14 +1171,29 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
11711171
AllowHigherAlign::Yes,
11721172
ForceRightAdjust::No,
11731173
),
1174+
Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => emit_ptr_va_arg(
1175+
bx,
1176+
addr,
1177+
target_ty,
1178+
PassMode::Direct,
1179+
match &target.llvm_abiname {
1180+
LlvmAbi::N32 | LlvmAbi::N64 => SlotSize::Bytes8,
1181+
LlvmAbi::O32 => SlotSize::Bytes4,
1182+
other => bug!("unexpected LLVM ABI {other}"),
1183+
},
1184+
AllowHigherAlign::Yes,
1185+
// In big-endian mode the actual value is stored in the right side of the slot, meaning
1186+
// that when the value is smaller than a slot, we need to adjust the pointer we read
1187+
// to somewhere in the middle of the slot.
1188+
match bx.tcx().sess.target.endian {
1189+
Endian::Big => ForceRightAdjust::Yes,
1190+
Endian::Little => ForceRightAdjust::No,
1191+
},
1192+
),
11741193

11751194
Arch::Bpf => bug!("bpf does not support c-variadic functions"),
11761195
Arch::SpirV => bug!("spirv does not support c-variadic functions"),
11771196

1178-
Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => {
1179-
// FIXME: port MipsTargetLowering::lowerVAARG.
1180-
bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx))
1181-
}
11821197
Arch::Sparc | Arch::Avr | Arch::M68k | Arch::Msp430 => {
11831198
// Clang uses the LLVM implementation for these architectures.
11841199
bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx))
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
//@ add-minicore
2+
//@ assembly-output: emit-asm
3+
//
4+
//@ revisions: MIPS MIPS64 MIPS64EL
5+
//@ [MIPS] compile-flags: -Copt-level=3 --target mips-unknown-linux-gnu
6+
//@ [MIPS] needs-llvm-components: mips
7+
//@ [MIPS64] compile-flags: -Copt-level=3 --target mipsisa64r6-unknown-linux-gnuabi64
8+
//@ [MIPS64] needs-llvm-components: mips
9+
//@ [MIPS64EL] compile-flags: -Copt-level=3 --target mips64el-unknown-linux-gnuabi64
10+
//@ [MIPS64EL] needs-llvm-components: mips
11+
#![feature(c_variadic, no_core, lang_items, intrinsics, rustc_attrs, asm_experimental_arch)]
12+
#![no_core]
13+
#![crate_type = "lib"]
14+
15+
// Check that the assembly that rustc generates matches what clang emits.
16+
17+
extern crate minicore;
18+
use minicore::*;
19+
20+
#[lang = "va_arg_safe"]
21+
pub unsafe trait VaArgSafe {}
22+
23+
unsafe impl VaArgSafe for i32 {}
24+
unsafe impl VaArgSafe for i64 {}
25+
unsafe impl VaArgSafe for f64 {}
26+
unsafe impl<T> VaArgSafe for *const T {}
27+
28+
#[repr(transparent)]
29+
struct VaListInner {
30+
ptr: *const c_void,
31+
}
32+
33+
#[repr(transparent)]
34+
#[lang = "va_list"]
35+
pub struct VaList<'a> {
36+
inner: VaListInner,
37+
_marker: PhantomData<&'a mut ()>,
38+
}
39+
40+
#[rustc_intrinsic]
41+
#[rustc_nounwind]
42+
pub const unsafe fn va_arg<T: VaArgSafe>(ap: &mut VaList<'_>) -> T;
43+
44+
#[unsafe(no_mangle)]
45+
unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 {
46+
// CHECK-LABEL: read_f64
47+
//
48+
// MIPS: lw $1, 0($4)
49+
// MIPS-NEXT: addiu $2, $zero, -8
50+
// MIPS-NEXT: addiu $1, $1, 7
51+
// MIPS-NEXT: and $1, $1, $2
52+
// MIPS-NEXT: addiu $2, $1, 8
53+
// MIPS-NEXT: sw $2, 0($4)
54+
// MIPS-NEXT: ldc1 $f0, 0($1)
55+
// MIPS-NEXT: jr $ra
56+
// MIPS-NEXT: nop
57+
//
58+
// MIPS64: ld $1, 0($4)
59+
// MIPS64-NEXT: daddiu $2, $1, 8
60+
// MIPS64-NEXT: sd $2, 0($4)
61+
// MIPS64-NEXT: ldc1 $f0, 0($1)
62+
// MIPS64-NEXT: jrc $ra
63+
//
64+
// MIPS64EL: ld $1, 0($4)
65+
// MIPS64EL-NEXT: daddiu $2, $1, 8
66+
// MIPS64EL-NEXT: sd $2, 0($4)
67+
// MIPS64EL-NEXT: ldc1 $f0, 0($1)
68+
// MIPS64EL-NEXT: jr $ra
69+
// MIPS64EL-NEXT: nop
70+
va_arg(ap)
71+
}
72+
73+
#[unsafe(no_mangle)]
74+
unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 {
75+
// CHECK-LABEL: read_i32
76+
//
77+
// MIPS: lw $1, 0($4)
78+
// MIPS-NEXT: addiu $2, $1, 4
79+
// MIPS-NEXT: sw $2, 0($4)
80+
// MIPS-NEXT: lw $2, 0($1)
81+
// MIPS-NEXT: jr $ra
82+
// MIPS-NEXT: nop
83+
//
84+
// MIPS64: ld $1, 0($4)
85+
// MIPS64-NEXT: daddiu $2, $1, 8
86+
// MIPS64-NEXT: sd $2, 0($4)
87+
// MIPS64-NEXT: lw $2, 4($1)
88+
// MIPS64-NEXT: jrc $ra
89+
//
90+
// MIPS64EL: ld $1, 0($4)
91+
// MIPS64EL-NEXT: daddiu $2, $1, 8
92+
// MIPS64EL-NEXT: sd $2, 0($4)
93+
// MIPS64EL-NEXT: lw $2, 0($1)
94+
// MIPS64EL-NEXT: jr $ra
95+
// MIPS64EL-NEXT: nop
96+
va_arg(ap)
97+
}
98+
99+
#[unsafe(no_mangle)]
100+
unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 {
101+
// CHECK-LABEL: read_i64
102+
//
103+
// MIPS: lw $1, 0($4)
104+
// MIPS-NEXT: addiu $2, $zero, -8
105+
// MIPS-NEXT: addiu $1, $1, 7
106+
// MIPS-NEXT: and $2, $1, $2
107+
// MIPS-NEXT: addiu $3, $2, 8
108+
// MIPS-NEXT: sw $3, 0($4)
109+
// MIPS-NEXT: addiu $3, $zero, 4
110+
// MIPS-NEXT: lw $2, 0($2)
111+
// MIPS-NEXT: ins $1, $3, 0, 3
112+
// MIPS-NEXT: lw $3, 0($1)
113+
// MIPS-NEXT: jr $ra
114+
// MIPS-NEXT: nop
115+
//
116+
// MIPS64: ld $1, 0($4)
117+
// MIPS64-NEXT: daddiu $2, $1, 8
118+
// MIPS64-NEXT: sd $2, 0($4)
119+
// MIPS64-NEXT: ld $2, 0($1)
120+
// MIPS64-NEXT: jrc $ra
121+
//
122+
// MIPS64EL: ld $1, 0($4)
123+
// MIPS64EL-NEXT: daddiu $2, $1, 8
124+
// MIPS64EL-NEXT: sd $2, 0($4)
125+
// MIPS64EL-NEXT: ld $2, 0($1)
126+
// MIPS64EL-NEXT: jr $ra
127+
// MIPS64EL-NEXT: nop
128+
va_arg(ap)
129+
}
130+
131+
#[unsafe(no_mangle)]
132+
unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 {
133+
// MIPS: read_ptr = read_i32
134+
// MIPS64: read_ptr = read_i64
135+
// MIPS64EL: read_ptr = read_i64
136+
va_arg(ap)
137+
}

0 commit comments

Comments
 (0)