Skip to content

Commit 3d308ee

Browse files
authored
Rollup merge of rust-lang#59577 - dlrobertson:fix_58881, r=nagisa
Fix LLVM IR generated for C-variadic arguments It is possible to create malformed LLVM IR given variadic arguments that are aggregate types. This occurs due to improper tracking of the current argument in the functions list of arguments. Fixes: rust-lang#58881
2 parents 6ee2c10 + 9095feb commit 3d308ee

File tree

2 files changed

+13
-14
lines changed

2 files changed

+13
-14
lines changed

src/librustc_codegen_ssa/mir/block.rs

+2-13
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use syntax_pos::Pos;
2020

2121
use super::{FunctionCx, LocalRef};
2222
use super::place::PlaceRef;
23-
use super::operand::{OperandValue, OperandRef};
23+
use super::operand::OperandRef;
2424
use super::operand::OperandValue::{Pair, Ref, Immediate};
2525

2626
/// Used by `FunctionCx::codegen_terminator` for emitting common patterns
@@ -695,18 +695,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
695695
// an "spoofed" `VaList`. This argument is ignored, but we need to
696696
// populate it with a dummy operand so that the users real arguments
697697
// are not overwritten.
698-
let i = if sig.c_variadic && last_arg_idx.map(|x| x == i).unwrap_or(false) {
699-
let layout = match self.cx.tcx().lang_items().va_list() {
700-
Some(did) => bx.cx().layout_of(bx.tcx().type_of(did)),
701-
None => bug!("`va_list` language item required for C-variadics"),
702-
};
703-
let op = OperandRef {
704-
val: OperandValue::Immediate(
705-
bx.cx().const_undef(bx.cx().immediate_backend_type(layout)
706-
)),
707-
layout: layout,
708-
};
709-
self.codegen_argument(&mut bx, op, &mut llargs, &fn_ty.args[i]);
698+
let i = if sig.c_variadic && last_arg_idx.map(|x| i >= x).unwrap_or(false) {
710699
if i + 1 < fn_ty.args.len() {
711700
i + 1
712701
} else {

src/test/codegen/c-variadic.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// compile-flags: -C no-prepopulate-passes
2+
// ignore-tidy-linelength
23

34
#![crate_type = "lib"]
45
#![feature(c_variadic)]
@@ -57,7 +58,7 @@ pub unsafe extern "C" fn c_variadic(n: i32, mut ap: ...) -> i32 {
5758

5859
// Ensure that we generate the correct `call` signature when calling a Rust
5960
// defined C-variadic.
60-
pub unsafe fn test_c_variadic_call() {
61+
pub unsafe fn test_c_variadic_call_0() {
6162
// CHECK: call i32 (i32, ...) @c_variadic(i32 0)
6263
c_variadic(0);
6364
// CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42)
@@ -67,3 +68,12 @@ pub unsafe fn test_c_variadic_call() {
6768
// CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42, i32 1024, i32 0)
6869
c_variadic(0, 42i32, 1024i32, 0i32);
6970
}
71+
72+
struct Foo(u64, u64);
73+
struct Bar(u64, u64, u64);
74+
75+
// Ensure that emit arguments of the correct type.
76+
pub unsafe fn test_c_variadic_call_1() {
77+
// CHECK: call void (i32, ...) @foreign_c_variadic_0(i32 0, { i64, i64 } %{{.*}}, %Bar* byval noalias nocapture dereferenceable(24) %{{.*}})
78+
foreign_c_variadic_0(0, Foo(0, 0), Bar(0, 0, 0));
79+
}

0 commit comments

Comments
 (0)