mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-06 08:36:52 -04:00
c-variadic: gate va_arg on c_variadic_experimental_arch
Just gating `...` is insufficient because we make the types available everywhere, and you could still define and export functions that used va_arg for targets where we don't want to stably support it.
This commit is contained in:
@@ -3,8 +3,8 @@ use std::ffi::c_uint;
|
||||
use std::{assert_matches, iter, ptr};
|
||||
|
||||
use rustc_abi::{
|
||||
AddressSpace, Align, BackendRepr, Float, HasDataLayout, Integer, NumScalableVectors, Primitive,
|
||||
Size, WrappingRange,
|
||||
AddressSpace, Align, BackendRepr, CVariadicStatus, Float, HasDataLayout, Integer,
|
||||
NumScalableVectors, Primitive, Size, WrappingRange,
|
||||
};
|
||||
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
|
||||
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||
@@ -23,6 +23,7 @@ use rustc_middle::ty::{
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_session::errors::feature_err;
|
||||
use rustc_session::lint::builtin::DEPRECATED_LLVM_INTRINSIC;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_symbol_mangling::{mangle_internal_symbol, symbol_name_for_instance_in_crate};
|
||||
@@ -288,6 +289,16 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
||||
}
|
||||
sym::breakpoint => self.call_intrinsic("llvm.debugtrap", &[], &[]),
|
||||
sym::va_arg => {
|
||||
let target = &self.cx.tcx.sess.target;
|
||||
let stability = target.supports_c_variadic_definitions();
|
||||
if let CVariadicStatus::Unstable { feature } = stability
|
||||
&& !self.tcx.features().enabled(feature)
|
||||
{
|
||||
let msg =
|
||||
format!("C-variadic function definitions on this target are unstable");
|
||||
feature_err(&*self.sess(), feature, span, msg).emit();
|
||||
}
|
||||
|
||||
let BackendRepr::Scalar(scalar) = result.layout.backend_repr else {
|
||||
bug!("the va_arg intrinsic does not support non-scalar types")
|
||||
};
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
//@ add-minicore
|
||||
//@ assembly-output: emit-asm
|
||||
//
|
||||
//@ revisions: AVR
|
||||
//@ [AVR] compile-flags: -Copt-level=3 --target=avr-none -Ctarget-cpu=atmega328p
|
||||
//@ [AVR] needs-llvm-components: avr
|
||||
#![feature(c_variadic, c_variadic_experimental_arch, no_core, lang_items, intrinsics, rustc_attrs)]
|
||||
#![no_core]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// Check that rustc and clang output match, see https://godbolt.org/z/1MvxoceeT.
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
#[lang = "va_arg_safe"]
|
||||
pub unsafe trait VaArgSafe {}
|
||||
|
||||
unsafe impl VaArgSafe for i16 {}
|
||||
unsafe impl VaArgSafe for i32 {}
|
||||
unsafe impl VaArgSafe for i64 {}
|
||||
unsafe impl VaArgSafe for f32 {}
|
||||
unsafe impl VaArgSafe for f64 {}
|
||||
unsafe impl<T> VaArgSafe for *const T {}
|
||||
|
||||
#[repr(transparent)]
|
||||
struct VaListInner {
|
||||
ptr: *const c_void,
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[lang = "va_list"]
|
||||
pub struct VaList<'a> {
|
||||
inner: VaListInner,
|
||||
_marker: PhantomData<&'a mut ()>,
|
||||
}
|
||||
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub const unsafe fn va_arg<T: VaArgSafe>(ap: &mut VaList<'_>) -> T;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn read_f32(ap: &mut VaList<'_>) -> f32 {
|
||||
// CHECK-LABEL: read_f32
|
||||
//
|
||||
// AVR: movw r30, r24
|
||||
// AVR-NEXT: ld r24, Z
|
||||
// AVR-NEXT: ldd r25, Z+1
|
||||
// AVR-NEXT: movw r26, r24
|
||||
// AVR-NEXT: adiw r26, 2
|
||||
// AVR-NEXT: std Z+1, r27
|
||||
// AVR-NEXT: st Z, r26
|
||||
// AVR-NEXT: movw r20, r30
|
||||
// AVR-NEXT: movw r18, r24
|
||||
// AVR-NEXT: movw r30, r18
|
||||
// AVR-NEXT: ld r22, Z
|
||||
// AVR-NEXT: ldd r23, Z+1
|
||||
// AVR-NEXT: adiw r24, 4
|
||||
// AVR-NEXT: movw r30, r20
|
||||
// AVR-NEXT: std Z+1, r25
|
||||
// AVR-NEXT: st Z, r24
|
||||
// AVR-NEXT: movw r30, r18
|
||||
// AVR-NEXT: ldd r24, Z+2
|
||||
// AVR-NEXT: ldd r25, Z+3
|
||||
// AVR-NEXT: ret
|
||||
va_arg(ap)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 {
|
||||
// CHECK-LABEL: read_f64
|
||||
//
|
||||
// AVR: push r14
|
||||
// AVR-NEXT: push r15
|
||||
// AVR-NEXT: push r16
|
||||
// AVR-NEXT: push r17
|
||||
// AVR-NEXT: movw r30, r24
|
||||
// AVR-NEXT: ld r24, Z
|
||||
// AVR-NEXT: ldd r25, Z+1
|
||||
// AVR-NEXT: movw r26, r24
|
||||
// AVR-NEXT: adiw r26, 2
|
||||
// AVR-NEXT: std Z+1, r27
|
||||
// AVR-NEXT: st Z, r26
|
||||
// AVR-NEXT: movw r14, r30
|
||||
// AVR-NEXT: movw r16, r24
|
||||
// AVR-NEXT: movw r30, r16
|
||||
// AVR-NEXT: ld r18, Z
|
||||
// AVR-NEXT: ldd r19, Z+1
|
||||
// AVR-NEXT: movw r26, r24
|
||||
// AVR-NEXT: adiw r26, 4
|
||||
// AVR-NEXT: movw r30, r14
|
||||
// AVR-NEXT: std Z+1, r27
|
||||
// AVR-NEXT: st Z, r26
|
||||
// AVR-NEXT: movw r30, r16
|
||||
// AVR-NEXT: ldd r20, Z+2
|
||||
// AVR-NEXT: ldd r21, Z+3
|
||||
// AVR-NEXT: movw r26, r24
|
||||
// AVR-NEXT: adiw r26, 6
|
||||
// AVR-NEXT: movw r30, r14
|
||||
// AVR-NEXT: std Z+1, r27
|
||||
// AVR-NEXT: st Z, r26
|
||||
// AVR-NEXT: movw r30, r16
|
||||
// AVR-NEXT: ldd r22, Z+4
|
||||
// AVR-NEXT: ldd r23, Z+5
|
||||
// AVR-NEXT: adiw r24, 8
|
||||
// AVR-NEXT: movw r30, r14
|
||||
// AVR-NEXT: std Z+1, r25
|
||||
// AVR-NEXT: st Z, r24
|
||||
// AVR-NEXT: movw r30, r16
|
||||
// AVR-NEXT: ldd r24, Z+6
|
||||
// AVR-NEXT: ldd r25, Z+7
|
||||
// AVR-NEXT: pop r17
|
||||
// AVR-NEXT: pop r16
|
||||
// AVR-NEXT: pop r15
|
||||
// AVR-NEXT: pop r14
|
||||
// AVR-NEXT: ret
|
||||
va_arg(ap)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn read_i16(ap: &mut VaList<'_>) -> i16 {
|
||||
// CHECK-LABEL: read_i16
|
||||
//
|
||||
// AVR: movw r30, r24
|
||||
// AVR-NEXT: ld r24, Z
|
||||
// AVR-NEXT: ldd r25, Z+1
|
||||
// AVR-NEXT: movw r26, r24
|
||||
// AVR-NEXT: adiw r26, 2
|
||||
// AVR-NEXT: std Z+1, r27
|
||||
// AVR-NEXT: st Z, r26
|
||||
// AVR-NEXT: movw r30, r24
|
||||
// AVR-NEXT: ld r24, Z
|
||||
// AVR-NEXT: ldd r25, Z+1
|
||||
// AVR-NEXT: ret
|
||||
va_arg(ap)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 {
|
||||
// CHECK-LABEL: read_i32
|
||||
//
|
||||
// AVR: movw r30, r24
|
||||
// AVR-NEXT: ld r24, Z
|
||||
// AVR-NEXT: ldd r25, Z+1
|
||||
// AVR-NEXT: movw r26, r24
|
||||
// AVR-NEXT: adiw r26, 2
|
||||
// AVR-NEXT: std Z+1, r27
|
||||
// AVR-NEXT: st Z, r26
|
||||
// AVR-NEXT: movw r20, r30
|
||||
// AVR-NEXT: movw r18, r24
|
||||
// AVR-NEXT: movw r30, r18
|
||||
// AVR-NEXT: ld r22, Z
|
||||
// AVR-NEXT: ldd r23, Z+1
|
||||
// AVR-NEXT: adiw r24, 4
|
||||
// AVR-NEXT: movw r30, r20
|
||||
// AVR-NEXT: std Z+1, r25
|
||||
// AVR-NEXT: st Z, r24
|
||||
// AVR-NEXT: movw r30, r18
|
||||
// AVR-NEXT: ldd r24, Z+2
|
||||
// AVR-NEXT: ldd r25, Z+3
|
||||
// AVR-NEXT: ret
|
||||
va_arg(ap)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 {
|
||||
// CHECK-LABEL: read_i64
|
||||
//
|
||||
// AVR: push r14
|
||||
// AVR-NEXT: push r15
|
||||
// AVR-NEXT: push r16
|
||||
// AVR-NEXT: push r17
|
||||
// AVR-NEXT: movw r30, r24
|
||||
// AVR-NEXT: ld r24, Z
|
||||
// AVR-NEXT: ldd r25, Z+1
|
||||
// AVR-NEXT: movw r26, r24
|
||||
// AVR-NEXT: adiw r26, 2
|
||||
// AVR-NEXT: std Z+1, r27
|
||||
// AVR-NEXT: st Z, r26
|
||||
// AVR-NEXT: movw r14, r30
|
||||
// AVR-NEXT: movw r16, r24
|
||||
// AVR-NEXT: movw r30, r16
|
||||
// AVR-NEXT: ld r18, Z
|
||||
// AVR-NEXT: ldd r19, Z+1
|
||||
// AVR-NEXT: movw r26, r24
|
||||
// AVR-NEXT: adiw r26, 4
|
||||
// AVR-NEXT: movw r30, r14
|
||||
// AVR-NEXT: std Z+1, r27
|
||||
// AVR-NEXT: st Z, r26
|
||||
// AVR-NEXT: movw r30, r16
|
||||
// AVR-NEXT: ldd r20, Z+2
|
||||
// AVR-NEXT: ldd r21, Z+3
|
||||
// AVR-NEXT: movw r26, r24
|
||||
// AVR-NEXT: adiw r26, 6
|
||||
// AVR-NEXT: movw r30, r14
|
||||
// AVR-NEXT: std Z+1, r27
|
||||
// AVR-NEXT: st Z, r26
|
||||
// AVR-NEXT: movw r30, r16
|
||||
// AVR-NEXT: ldd r22, Z+4
|
||||
// AVR-NEXT: ldd r23, Z+5
|
||||
// AVR-NEXT: adiw r24, 8
|
||||
// AVR-NEXT: movw r30, r14
|
||||
// AVR-NEXT: std Z+1, r25
|
||||
// AVR-NEXT: st Z, r24
|
||||
// AVR-NEXT: movw r30, r16
|
||||
// AVR-NEXT: ldd r24, Z+6
|
||||
// AVR-NEXT: ldd r25, Z+7
|
||||
// AVR-NEXT: pop r17
|
||||
// AVR-NEXT: pop r16
|
||||
// AVR-NEXT: pop r15
|
||||
// AVR-NEXT: pop r14
|
||||
// AVR-NEXT: ret
|
||||
va_arg(ap)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 {
|
||||
// AVR: read_ptr = pm(read_i16)
|
||||
va_arg(ap)
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
//@ [SPARC64] compile-flags: -Copt-level=3 --target sparc64-unknown-linux-gnu
|
||||
//@ [SPARC64] needs-llvm-components: sparc
|
||||
#![feature(c_variadic, no_core, lang_items, intrinsics, rustc_attrs, asm_experimental_arch)]
|
||||
#![cfg_attr(target_arch = "sparc", feature(c_variadic_experimental_arch))]
|
||||
#![no_core]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user