Skip to content

Commit 225796a

Browse files
committed
Add method to get FnAbi of function pointer
1 parent 4e6de37 commit 225796a

File tree

4 files changed

+44
-1
lines changed

4 files changed

+44
-1
lines changed

compiler/rustc_smir/src/rustc_smir/context.rs

+7
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
533533
Ok(tables.fn_abi_of_instance(instance, List::empty())?.stable(&mut *tables))
534534
}
535535

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+
536543
fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
537544
let mut tables = self.0.borrow_mut();
538545
let def_id = tables.instances[def].def_id();

compiler/stable_mir/src/compiler_interface.rs

+3
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ pub trait Context {
215215
/// Get an instance ABI.
216216
fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error>;
217217

218+
/// Get the ABI of a function pointer.
219+
fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error>;
220+
218221
/// Get the layout of a type.
219222
fn ty_layout(&self, ty: Ty) -> Result<Layout, Error>;
220223

compiler/stable_mir/src/ty.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::{
22
mir::{Body, Mutability, Safety},
33
with, DefId, Error, Symbol,
44
};
5-
use crate::abi::Layout;
5+
use crate::abi::{FnAbi, Layout};
66
use crate::crate_def::{CrateDef, CrateDefType};
77
use crate::mir::alloc::{read_target_int, read_target_uint, AllocId};
88
use crate::mir::mono::StaticDef;
@@ -996,6 +996,16 @@ pub struct AliasTerm {
996996

997997
pub type PolyFnSig = Binder<FnSig>;
998998

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| cx.fn_ptr_abi(self))
1006+
}
1007+
}
1008+
9991009
#[derive(Clone, Debug, Eq, PartialEq)]
10001010
pub struct FnSig {
10011011
pub inputs_and_output: Vec<Ty>,

tests/ui-fulldeps/stable-mir/check_abi.rs

+23
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,21 @@ fn test_stable_mir() -> ControlFlow<()> {
5454
let variadic_fn = *get_item(&items, (ItemKind::Fn, "variadic_fn")).unwrap();
5555
check_variadic(variadic_fn);
5656

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+
5772
ControlFlow::Continue(())
5873
}
5974

@@ -164,6 +179,14 @@ fn generate_input(path: &str) -> std::io::Result<()> {
164179
pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) -> usize {{
165180
0
166181
}}
182+
183+
pub type ComplexFn = fn([u8; 0], char, NonZero<u8>) -> 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+
}}
167190
"#
168191
)?;
169192
Ok(())

0 commit comments

Comments
 (0)