@@ -23,7 +23,7 @@ use rustc_middle::ty::TyCtxt;
2323use rustc_smir:: rustc_internal;
2424use stable_mir:: abi:: { ArgAbi , CallConvention , FieldsShape , PassMode , VariantsShape } ;
2525use stable_mir:: mir:: mono:: Instance ;
26- use stable_mir:: { CrateDef , CrateItems , ItemKind } ;
26+ use stable_mir:: { CrateDef , CrateItem , CrateItems , ItemKind } ;
2727use std:: assert_matches:: assert_matches;
2828use std:: convert:: TryFrom ;
2929use std:: io:: Write ;
@@ -35,6 +35,8 @@ const CRATE_NAME: &str = "input";
3535fn test_stable_mir ( _tcx : TyCtxt < ' _ > ) -> ControlFlow < ( ) > {
3636 // Find items in the local crate.
3737 let items = stable_mir:: all_local_items ( ) ;
38+
39+ // Test fn_abi
3840 let target_fn = * get_item ( & items, ( ItemKind :: Fn , "fn_abi" ) ) . unwrap ( ) ;
3941 let instance = Instance :: try_from ( target_fn) . unwrap ( ) ;
4042 let fn_abi = instance. fn_abi ( ) . unwrap ( ) ;
@@ -45,9 +47,26 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
4547 check_primitive ( & fn_abi. args [ 1 ] ) ;
4648 check_result ( fn_abi. ret ) ;
4749
50+ // Test variadic function.
51+ let variadic_fn = * get_item ( & items, ( ItemKind :: Fn , "variadic_fn" ) ) . unwrap ( ) ;
52+ check_variadic ( variadic_fn) ;
53+
4854 ControlFlow :: Continue ( ( ) )
4955}
5056
57+ /// Check the variadic function ABI:
58+ /// ```no_run
59+ /// pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) -> usize {
60+ /// 0
61+ /// }
62+ /// ```
63+ fn check_variadic ( variadic_fn : CrateItem ) {
64+ let instance = Instance :: try_from ( variadic_fn) . unwrap ( ) ;
65+ let abi = instance. fn_abi ( ) . unwrap ( ) ;
66+ assert ! ( abi. c_variadic) ;
67+ assert_eq ! ( abi. args. len( ) , 1 ) ;
68+ }
69+
5170/// Check the argument to be ignored: `ignore: [u8; 0]`.
5271fn check_ignore ( abi : & ArgAbi ) {
5372 assert ! ( abi. ty. kind( ) . is_array( ) ) ;
@@ -60,7 +79,7 @@ fn check_ignore(abi: &ArgAbi) {
6079/// Check the primitive argument: `primitive: char`.
6180fn check_primitive ( abi : & ArgAbi ) {
6281 assert ! ( abi. ty. kind( ) . is_char( ) ) ;
63- assert_eq ! ( abi. mode, PassMode :: Direct ) ;
82+ assert_matches ! ( abi. mode, PassMode :: Direct ( _ ) ) ;
6483 let layout = abi. layout . shape ( ) ;
6584 assert ! ( layout. is_sized( ) ) ;
6685 assert ! ( !layout. is_1zst( ) ) ;
@@ -70,7 +89,7 @@ fn check_primitive(abi: &ArgAbi) {
7089/// Check the return value: `Result<usize, &str>`.
7190fn check_result ( abi : ArgAbi ) {
7291 assert ! ( abi. ty. kind( ) . is_enum( ) ) ;
73- assert_eq ! ( abi. mode, PassMode :: Indirect ) ;
92+ assert_matches ! ( abi. mode, PassMode :: Indirect { .. } ) ;
7493 let layout = abi. layout . shape ( ) ;
7594 assert ! ( layout. is_sized( ) ) ;
7695 assert_matches ! ( layout. fields, FieldsShape :: Arbitrary { .. } ) ;
@@ -106,11 +125,18 @@ fn generate_input(path: &str) -> std::io::Result<()> {
106125 write ! (
107126 file,
108127 r#"
109- #[allow(unused_variables)]
128+ #![feature(c_variadic)]
129+ #![allow(unused_variables)]
130+
110131 pub fn fn_abi(ignore: [u8; 0], primitive: char) -> Result<usize, &'static str> {{
111132 // We only care about the signature.
112133 todo!()
113134 }}
135+
136+
137+ pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) -> usize {{
138+ 0
139+ }}
114140 "#
115141 ) ?;
116142 Ok ( ( ) )
0 commit comments