Skip to content

Commit fa740c7

Browse files
committed
refactor llvm va_arg intrinsic validation logic
1 parent a852582 commit fa740c7

1 file changed

Lines changed: 15 additions & 8 deletions

File tree

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use std::ffi::c_uint;
33
use std::{assert_matches, iter, ptr};
44

55
use rustc_abi::{
6-
Align, BackendRepr, Float, HasDataLayout, NumScalableVectors, Primitive, Size, WrappingRange,
6+
Align, BackendRepr, Float, HasDataLayout, Integer, NumScalableVectors, Primitive, Size,
7+
WrappingRange,
78
};
89
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
910
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
@@ -288,10 +289,17 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
288289
bug!("the va_arg intrinsic does not support non-scalar types")
289290
};
290291

292+
// We reject types that would never be passed as varargs in C because
293+
// they get promoted to a larger type, specifically integers smaller than
294+
// c_int and float type smaller than c_double.
291295
match scalar.primitive() {
292296
Primitive::Pointer(_) => {
293297
// Pointers are always OK.
294-
emit_va_arg(self, args[0], result.layout.ty)
298+
}
299+
Primitive::Int(Integer::I128, _) => {
300+
// FIXME: maybe we should support these? At least on 32-bit powerpc
301+
// the logic in LLVM does not handle i128 correctly though.
302+
bug!("the va_arg intrinsic does not support `i128`/`u128`")
295303
}
296304
Primitive::Int(..) => {
297305
let int_width = self.cx().size_of(result.layout.ty).bits();
@@ -305,27 +313,26 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
305313
target_c_int_width
306314
);
307315
}
308-
emit_va_arg(self, args[0], result.layout.ty)
309316
}
310317
Primitive::Float(Float::F16) => {
311318
bug!("the va_arg intrinsic does not support `f16`")
312319
}
313320
Primitive::Float(Float::F32) => {
314-
if self.cx().sess().target.arch == Arch::Avr {
315-
// c_double is actually f32 on avr.
316-
emit_va_arg(self, args[0], result.layout.ty)
317-
} else {
321+
// c_double is actually f32 on avr.
322+
if self.cx().sess().target.arch != Arch::Avr {
318323
bug!("the va_arg intrinsic does not support `f32` on this target")
319324
}
320325
}
321326
Primitive::Float(Float::F64) => {
322327
// 64-bit floats are always OK.
323-
emit_va_arg(self, args[0], result.layout.ty)
324328
}
325329
Primitive::Float(Float::F128) => {
330+
// FIXME(f128) figure out whether we should support this.
326331
bug!("the va_arg intrinsic does not support `f128`")
327332
}
328333
}
334+
335+
emit_va_arg(self, args[0], result.layout.ty)
329336
}
330337

331338
sym::volatile_load | sym::unaligned_volatile_load => {

0 commit comments

Comments
 (0)