Skip to content

Commit 896022a

Browse files
committed
Auto merge of #155429 - folkertdev:c-variadic-i128, r=<try>
Support `u128`/`i128` c-variadic arguments try-job: dist-various-1 try-job: dist-various-2 try-job: aarch64-apple try-job: x86_64-mingw-1
2 parents 1b8f2e4 + 49ef484 commit 896022a

4 files changed

Lines changed: 29 additions & 6 deletions

File tree

compiler/rustc_codegen_llvm/src/va_arg.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ fn round_pointer_up_to_alignment<'ll>(
3232
let ptr = bx.inbounds_ptradd(addr, bx.const_i32(align.bytes() as i32 - 1));
3333
bx.call_intrinsic(
3434
"llvm.ptrmask",
35-
&[ptr_ty, bx.type_i32()],
36-
&[ptr, bx.const_int(bx.isize_ty, -(align.bytes() as isize) as i64)],
35+
&[ptr_ty, bx.type_isize()],
36+
&[ptr, bx.const_usize(align.bytes().wrapping_neg())],
3737
)
3838
}
3939

@@ -765,9 +765,16 @@ fn x86_64_sysv64_va_arg_from_memory<'ll, 'tcx>(
765765
// byte boundary if alignment needed by type exceeds 8 byte boundary.
766766
// It isn't stated explicitly in the standard, but in practice we use
767767
// alignment greater than 16 where necessary.
768-
if layout.layout.align.bytes() > 8 {
769-
unreachable!("all instances of VaArgSafe have an alignment <= 8");
770-
}
768+
let overflow_arg_area_v = if layout.layout.align.bytes() > 8 {
769+
round_pointer_up_to_alignment(
770+
bx,
771+
overflow_arg_area_v,
772+
layout.layout.align.abi,
773+
bx.type_ptr(),
774+
)
775+
} else {
776+
overflow_arg_area_v
777+
};
771778

772779
// AMD64-ABI 3.5.7p5: Step 8. Fetch type from l->overflow_arg_area.
773780
let mem_addr = overflow_arg_area_v;

library/core/src/ffi/va_list.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,12 @@ mod sealed {
268268

269269
impl Sealed for i32 {}
270270
impl Sealed for i64 {}
271+
impl Sealed for i128 {}
271272
impl Sealed for isize {}
272273

273274
impl Sealed for u32 {}
274275
impl Sealed for u64 {}
276+
impl Sealed for u128 {}
275277
impl Sealed for usize {}
276278

277279
impl Sealed for f64 {}
@@ -302,11 +304,13 @@ pub unsafe trait VaArgSafe: sealed::Sealed {}
302304
// i8 and i16 are implicitly promoted to c_int in C, and cannot implement `VaArgSafe`.
303305
unsafe impl VaArgSafe for i32 {}
304306
unsafe impl VaArgSafe for i64 {}
307+
unsafe impl VaArgSafe for i128 {}
305308
unsafe impl VaArgSafe for isize {}
306309

307310
// u8 and u16 are implicitly promoted to c_int in C, and cannot implement `VaArgSafe`.
308311
unsafe impl VaArgSafe for u32 {}
309312
unsafe impl VaArgSafe for u64 {}
313+
unsafe impl VaArgSafe for u128 {}
310314
unsafe impl VaArgSafe for usize {}
311315

312316
// f32 is implicitly promoted to c_double in C, and cannot implement `VaArgSafe`.

tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub unsafe extern "C" fn check_list_0(mut ap: VaList) -> usize {
2020
continue_if!(ap.arg::<c_longlong>() == 1);
2121
continue_if!(ap.arg::<c_int>() == 2);
2222
continue_if!(ap.arg::<c_longlong>() == 3);
23+
continue_if!(ap.arg::<i128>() == 4);
2324
0
2425
}
2526

@@ -57,6 +58,14 @@ pub unsafe extern "C" fn check_list_copy_0(mut ap: VaList) -> usize {
5758
if compare_c_str(ap.arg::<*const c_char>(), c"Correct") { 0 } else { 0xff }
5859
}
5960

61+
#[unsafe(no_mangle)]
62+
pub unsafe extern "C" fn check_list_i128(mut ap: VaList) -> usize {
63+
continue_if!(ap.arg::<i128>() == -42);
64+
continue_if!(ap.arg::<c_int>() == 0xAAAA_AAAAu32.cast_signed());
65+
continue_if!(ap.arg::<u128>() == u128::MAX);
66+
0
67+
}
68+
6069
#[unsafe(no_mangle)]
6170
pub unsafe extern "C" fn check_varargs_0(_: c_int, mut ap: ...) -> usize {
6271
continue_if!(ap.arg::<c_int>() == 42);

tests/run-make/c-link-to-rust-va-list-fn/test.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extern size_t check_list_0(va_list ap);
88
extern size_t check_list_1(va_list ap);
99
extern size_t check_list_2(va_list ap);
1010
extern size_t check_list_copy_0(va_list ap);
11+
extern size_t check_list_i128(va_list ap);
1112
extern size_t check_varargs_0(int fixed, ...);
1213
extern size_t check_varargs_1(int fixed, ...);
1314
extern size_t check_varargs_2(int fixed, ...);
@@ -30,14 +31,16 @@ int test_rust(size_t (*fn)(va_list), ...) {
3031
}
3132

3233
int main(int argc, char* argv[]) {
33-
assert(test_rust(check_list_0, 0x01LL, 0x02, 0x03LL) == 0);
34+
assert(test_rust(check_list_0, 0x01LL, 0x02, 0x03LL, (__int128)4) == 0);
3435

3536
assert(test_rust(check_list_1, -1, 'A', '4', ';', 0x32, 0x10000001, "Valid!") == 0);
3637

3738
assert(test_rust(check_list_2, 3.14, 12l, 'a', 6.28, "Hello", 42, "World") == 0);
3839

3940
assert(test_rust(check_list_copy_0, 6.28, 16, 'A', "Skip Me!", "Correct") == 0);
4041

42+
assert(test_rust(check_list_i128, (__int128)-42, 0xAAAAAAAA, (unsigned __int128)-1) == 0);
43+
4144
assert(check_varargs_0(0, 42, "Hello, World!") == 0);
4245

4346
assert(check_varargs_1(0, 3.14, 12l, 'A', 0x1LL) == 0);

0 commit comments

Comments
 (0)