Rollup merge of #126722 - adwinwhite:ptr_fn_abi, r=celinval · rust-lang/rust@1f9793f (original) (raw)

File tree

4 files changed

lines changed

4 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -533,6 +533,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
533 533 Ok(tables.fn_abi_of_instance(instance, List::empty())?.stable(&mut *tables))
534 534 }
535 535
536 +fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> {
537 +let mut tables = self.0.borrow_mut();
538 +let tcx = tables.tcx;
539 +let sig = fn_ptr.internal(&mut *tables, tcx);
540 +Ok(tables.fn_abi_of_fn_ptr(sig, List::empty())?.stable(&mut *tables))
541 +}
542 +
536 543 fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
537 544 let mut tables = self.0.borrow_mut();
538 545 let def_id = tables.instances[def].def_id();
Original file line number Diff line number Diff line change
@@ -215,6 +215,9 @@ pub trait Context {
215 215 /// Get an instance ABI.
216 216 fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error>;
217 217
218 +/// Get the ABI of a function pointer.
219 + fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error>;
220 +
218 221 /// Get the layout of a type.
219 222 fn ty_layout(&self, ty: Ty) -> Result<Layout, Error>;
220 223
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ use super::{
2 2 mir::{Body, Mutability, Safety},
3 3 with, DefId, Error, Symbol,
4 4 };
5 -use crate::abi::Layout;
5 +use crate::abi::{FnAbi, Layout};
6 6 use crate::crate_def::{CrateDef, CrateDefType};
7 7 use crate::mir::alloc::{read_target_int, read_target_uint, AllocId};
8 8 use crate::mir::mono::StaticDef;
@@ -996,6 +996,16 @@ pub struct AliasTerm {
996 996
997 997 pub type PolyFnSig = Binder<FnSig>;
998 998
999 +impl PolyFnSig {
1000 +/// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
1001 + ///
1002 + /// NB: this doesn't handle virtual calls - those should use `Instance::fn_abi`
1003 + /// instead, where the instance is an `InstanceKind::Virtual`.
1004 + pub fn fn_ptr_abi(self) -> Result<FnAbi, Error> {
1005 +with(|cx
1006 +}
1007 +}
1008 +
999 1009 #[derive(Clone, Debug, Eq, PartialEq)]
1000 1010 pub struct FnSig {
1001 1011 pub inputs_and_output: Vec<Ty>,
Original file line number Diff line number Diff line change
@@ -54,6 +54,21 @@ fn test_stable_mir() -> ControlFlow<()> {
54 54 let variadic_fn = *get_item(&items, (ItemKind::Fn, "variadic_fn")).unwrap();
55 55 check_variadic(variadic_fn);
56 56
57 +// Extract function pointers.
58 +let fn_ptr_holder = *get_item(&items, (ItemKind::Fn, "fn_ptr_holder")).unwrap();
59 +let fn_ptr_holder_instance = Instance::try_from(fn_ptr_holder).unwrap();
60 +let body = fn_ptr_holder_instance.body().unwrap();
61 +let args = body.arg_locals();
62 +
63 +// Test fn_abi of function pointer version.
64 +let ptr_fn_abi = args[0].ty.kind().fn_sig().unwrap().fn_ptr_abi().unwrap();
65 +assert_eq!(ptr_fn_abi, fn_abi);
66 +
67 +// Test variadic_fn of function pointer version.
68 +let ptr_variadic_fn_abi = args[1].ty.kind().fn_sig().unwrap().fn_ptr_abi().unwrap();
69 +assert!(ptr_variadic_fn_abi.c_variadic);
70 +assert_eq!(ptr_variadic_fn_abi.args.len(), 1);
71 +
57 72 ControlFlow::Continue(())
58 73 }
59 74
@@ -164,6 +179,14 @@ fn generate_input(path: &str) -> std::io::Result<()> {
164 179 pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) -> usize {{
165 180 0
166 181 }}
182 +
183 + pub type ComplexFn = fn([u8; 0], char, NonZero) -> Result<usize, &'static str>;
184 + pub type VariadicFn = unsafe extern "C" fn(usize, ...) -> usize;
185 +
186 + pub fn fn_ptr_holder(complex_fn: ComplexFn, variadic_fn: VariadicFn) {{
187 + // We only care about the signature.
188 + todo!()
189 + }}
167 190 "#
168 191 )?;
169 192 Ok(())