mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 06:22:00 +00:00
Fix c_variadic flag and add opaque info to PassMode
We should expand the information in PassMode later.
This commit is contained in:
parent
1a83c5b55b
commit
76b3e6de55
@ -66,11 +66,14 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::FnAbi<'tcx, ty::Ty<'tcx>> {
|
|||||||
type T = FnAbi;
|
type T = FnAbi;
|
||||||
|
|
||||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
assert!(self.args.len() >= self.fixed_count as usize);
|
||||||
|
assert!(!self.c_variadic || matches!(self.conv, Conv::C));
|
||||||
FnAbi {
|
FnAbi {
|
||||||
args: self.args.as_ref().stable(tables),
|
args: self.args.as_ref().stable(tables),
|
||||||
ret: self.ret.stable(tables),
|
ret: self.ret.stable(tables),
|
||||||
fixed_count: self.fixed_count,
|
fixed_count: self.fixed_count,
|
||||||
conv: self.conv.stable(tables),
|
conv: self.conv.stable(tables),
|
||||||
|
c_variadic: self.c_variadic,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,10 +125,20 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::PassMode {
|
|||||||
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
match self {
|
match self {
|
||||||
rustc_target::abi::call::PassMode::Ignore => PassMode::Ignore,
|
rustc_target::abi::call::PassMode::Ignore => PassMode::Ignore,
|
||||||
rustc_target::abi::call::PassMode::Direct(_) => PassMode::Direct,
|
rustc_target::abi::call::PassMode::Direct(attr) => PassMode::Direct(opaque(attr)),
|
||||||
rustc_target::abi::call::PassMode::Pair(_, _) => PassMode::Pair,
|
rustc_target::abi::call::PassMode::Pair(first, second) => {
|
||||||
rustc_target::abi::call::PassMode::Cast { .. } => PassMode::Cast,
|
PassMode::Pair(opaque(first), opaque(second))
|
||||||
rustc_target::abi::call::PassMode::Indirect { .. } => PassMode::Indirect,
|
}
|
||||||
|
rustc_target::abi::call::PassMode::Cast { pad_i32, cast } => {
|
||||||
|
PassMode::Cast { pad_i32: *pad_i32, cast: opaque(cast) }
|
||||||
|
}
|
||||||
|
rustc_target::abi::call::PassMode::Indirect { attrs, meta_attrs, on_stack } => {
|
||||||
|
PassMode::Indirect {
|
||||||
|
attrs: opaque(attrs),
|
||||||
|
meta_attrs: opaque(meta_attrs),
|
||||||
|
on_stack: *on_stack,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,9 @@ pub struct FnAbi {
|
|||||||
|
|
||||||
/// The ABI convention.
|
/// The ABI convention.
|
||||||
pub conv: CallConvention,
|
pub conv: CallConvention,
|
||||||
}
|
|
||||||
|
|
||||||
impl FnAbi {
|
/// Whether this is a variadic C function,
|
||||||
pub fn is_c_variadic(&self) -> bool {
|
pub c_variadic: bool,
|
||||||
self.args.len() > self.fixed_count as usize
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about the ABI of a function's argument, or return value.
|
/// Information about the ABI of a function's argument, or return value.
|
||||||
@ -47,15 +44,15 @@ pub enum PassMode {
|
|||||||
/// Pass the argument directly.
|
/// Pass the argument directly.
|
||||||
///
|
///
|
||||||
/// The argument has a layout abi of `Scalar` or `Vector`.
|
/// The argument has a layout abi of `Scalar` or `Vector`.
|
||||||
Direct,
|
Direct(Opaque),
|
||||||
/// Pass a pair's elements directly in two arguments.
|
/// Pass a pair's elements directly in two arguments.
|
||||||
///
|
///
|
||||||
/// The argument has a layout abi of `ScalarPair`.
|
/// The argument has a layout abi of `ScalarPair`.
|
||||||
Pair,
|
Pair(Opaque, Opaque),
|
||||||
/// Pass the argument after casting it.
|
/// Pass the argument after casting it.
|
||||||
Cast,
|
Cast { pad_i32: bool, cast: Opaque },
|
||||||
/// Pass the argument indirectly via a hidden pointer.
|
/// Pass the argument indirectly via a hidden pointer.
|
||||||
Indirect,
|
Indirect { attrs: Opaque, meta_attrs: Opaque, on_stack: bool },
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The layout of a type, alongside the type itself.
|
/// The layout of a type, alongside the type itself.
|
||||||
|
@ -23,7 +23,7 @@ use rustc_middle::ty::TyCtxt;
|
|||||||
use rustc_smir::rustc_internal;
|
use rustc_smir::rustc_internal;
|
||||||
use stable_mir::abi::{ArgAbi, CallConvention, FieldsShape, PassMode, VariantsShape};
|
use stable_mir::abi::{ArgAbi, CallConvention, FieldsShape, PassMode, VariantsShape};
|
||||||
use stable_mir::mir::mono::Instance;
|
use stable_mir::mir::mono::Instance;
|
||||||
use stable_mir::{CrateDef, CrateItems, ItemKind};
|
use stable_mir::{CrateDef, CrateItem, CrateItems, ItemKind};
|
||||||
use std::assert_matches::assert_matches;
|
use std::assert_matches::assert_matches;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
@ -35,6 +35,8 @@ const CRATE_NAME: &str = "input";
|
|||||||
fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
|
fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
|
||||||
// Find items in the local crate.
|
// Find items in the local crate.
|
||||||
let items = stable_mir::all_local_items();
|
let items = stable_mir::all_local_items();
|
||||||
|
|
||||||
|
// Test fn_abi
|
||||||
let target_fn = *get_item(&items, (ItemKind::Fn, "fn_abi")).unwrap();
|
let target_fn = *get_item(&items, (ItemKind::Fn, "fn_abi")).unwrap();
|
||||||
let instance = Instance::try_from(target_fn).unwrap();
|
let instance = Instance::try_from(target_fn).unwrap();
|
||||||
let fn_abi = instance.fn_abi().unwrap();
|
let fn_abi = instance.fn_abi().unwrap();
|
||||||
@ -45,9 +47,26 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
|
|||||||
check_primitive(&fn_abi.args[1]);
|
check_primitive(&fn_abi.args[1]);
|
||||||
check_result(fn_abi.ret);
|
check_result(fn_abi.ret);
|
||||||
|
|
||||||
|
// Test variadic function.
|
||||||
|
let variadic_fn = *get_item(&items, (ItemKind::Fn, "variadic_fn")).unwrap();
|
||||||
|
check_variadic(variadic_fn);
|
||||||
|
|
||||||
ControlFlow::Continue(())
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check the variadic function ABI:
|
||||||
|
/// ```no_run
|
||||||
|
/// pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) -> usize {
|
||||||
|
/// 0
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
fn check_variadic(variadic_fn: CrateItem) {
|
||||||
|
let instance = Instance::try_from(variadic_fn).unwrap();
|
||||||
|
let abi = instance.fn_abi().unwrap();
|
||||||
|
assert!(abi.c_variadic);
|
||||||
|
assert_eq!(abi.args.len(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
/// Check the argument to be ignored: `ignore: [u8; 0]`.
|
/// Check the argument to be ignored: `ignore: [u8; 0]`.
|
||||||
fn check_ignore(abi: &ArgAbi) {
|
fn check_ignore(abi: &ArgAbi) {
|
||||||
assert!(abi.ty.kind().is_array());
|
assert!(abi.ty.kind().is_array());
|
||||||
@ -60,7 +79,7 @@ fn check_ignore(abi: &ArgAbi) {
|
|||||||
/// Check the primitive argument: `primitive: char`.
|
/// Check the primitive argument: `primitive: char`.
|
||||||
fn check_primitive(abi: &ArgAbi) {
|
fn check_primitive(abi: &ArgAbi) {
|
||||||
assert!(abi.ty.kind().is_char());
|
assert!(abi.ty.kind().is_char());
|
||||||
assert_eq!(abi.mode, PassMode::Direct);
|
assert_matches!(abi.mode, PassMode::Direct(_));
|
||||||
let layout = abi.layout.shape();
|
let layout = abi.layout.shape();
|
||||||
assert!(layout.is_sized());
|
assert!(layout.is_sized());
|
||||||
assert!(!layout.is_1zst());
|
assert!(!layout.is_1zst());
|
||||||
@ -70,7 +89,7 @@ fn check_primitive(abi: &ArgAbi) {
|
|||||||
/// Check the return value: `Result<usize, &str>`.
|
/// Check the return value: `Result<usize, &str>`.
|
||||||
fn check_result(abi: ArgAbi) {
|
fn check_result(abi: ArgAbi) {
|
||||||
assert!(abi.ty.kind().is_enum());
|
assert!(abi.ty.kind().is_enum());
|
||||||
assert_eq!(abi.mode, PassMode::Indirect);
|
assert_matches!(abi.mode, PassMode::Indirect { .. });
|
||||||
let layout = abi.layout.shape();
|
let layout = abi.layout.shape();
|
||||||
assert!(layout.is_sized());
|
assert!(layout.is_sized());
|
||||||
assert_matches!(layout.fields, FieldsShape::Arbitrary { .. });
|
assert_matches!(layout.fields, FieldsShape::Arbitrary { .. });
|
||||||
@ -106,11 +125,18 @@ fn generate_input(path: &str) -> std::io::Result<()> {
|
|||||||
write!(
|
write!(
|
||||||
file,
|
file,
|
||||||
r#"
|
r#"
|
||||||
#[allow(unused_variables)]
|
#![feature(c_variadic)]
|
||||||
|
#![allow(unused_variables)]
|
||||||
|
|
||||||
pub fn fn_abi(ignore: [u8; 0], primitive: char) -> Result<usize, &'static str> {{
|
pub fn fn_abi(ignore: [u8; 0], primitive: char) -> Result<usize, &'static str> {{
|
||||||
// We only care about the signature.
|
// We only care about the signature.
|
||||||
todo!()
|
todo!()
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) -> usize {{
|
||||||
|
0
|
||||||
|
}}
|
||||||
"#
|
"#
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
Loading…
Reference in New Issue
Block a user