Skip to content

Commit

Permalink
Add method to get FnAbi of function pointer
Browse files Browse the repository at this point in the history
  • Loading branch information
adwinwhite committed Jun 21, 2024
1 parent 4e6de37 commit 225796a
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 1 deletion.
7 changes: 7 additions & 0 deletions compiler/rustc_smir/src/rustc_smir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
Ok(tables.fn_abi_of_instance(instance, List::empty())?.stable(&mut *tables))
}

fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let sig = fn_ptr.internal(&mut *tables, tcx);
Ok(tables.fn_abi_of_fn_ptr(sig, List::empty())?.stable(&mut *tables))
}

fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
let mut tables = self.0.borrow_mut();
let def_id = tables.instances[def].def_id();
Expand Down
3 changes: 3 additions & 0 deletions compiler/stable_mir/src/compiler_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ pub trait Context {
/// Get an instance ABI.
fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error>;

/// Get the ABI of a function pointer.
fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error>;

/// Get the layout of a type.
fn ty_layout(&self, ty: Ty) -> Result<Layout, Error>;

Expand Down
12 changes: 11 additions & 1 deletion compiler/stable_mir/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::{
mir::{Body, Mutability, Safety},
with, DefId, Error, Symbol,
};
use crate::abi::Layout;
use crate::abi::{FnAbi, Layout};
use crate::crate_def::{CrateDef, CrateDefType};
use crate::mir::alloc::{read_target_int, read_target_uint, AllocId};
use crate::mir::mono::StaticDef;
Expand Down Expand Up @@ -996,6 +996,16 @@ pub struct AliasTerm {

pub type PolyFnSig = Binder<FnSig>;

impl PolyFnSig {
/// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
///
/// NB: this doesn't handle virtual calls - those should use `Instance::fn_abi`
/// instead, where the instance is an `InstanceKind::Virtual`.
pub fn fn_ptr_abi(self) -> Result<FnAbi, Error> {
with(|cx| cx.fn_ptr_abi(self))
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct FnSig {
pub inputs_and_output: Vec<Ty>,
Expand Down
23 changes: 23 additions & 0 deletions tests/ui-fulldeps/stable-mir/check_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,21 @@ fn test_stable_mir() -> ControlFlow<()> {
let variadic_fn = *get_item(&items, (ItemKind::Fn, "variadic_fn")).unwrap();
check_variadic(variadic_fn);

// Extract function pointers.
let fn_ptr_holder = *get_item(&items, (ItemKind::Fn, "fn_ptr_holder")).unwrap();
let fn_ptr_holder_instance = Instance::try_from(fn_ptr_holder).unwrap();
let body = fn_ptr_holder_instance.body().unwrap();
let args = body.arg_locals();

// Test fn_abi of function pointer version.
let ptr_fn_abi = args[0].ty.kind().fn_sig().unwrap().fn_ptr_abi().unwrap();
assert_eq!(ptr_fn_abi, fn_abi);

// Test variadic_fn of function pointer version.
let ptr_variadic_fn_abi = args[1].ty.kind().fn_sig().unwrap().fn_ptr_abi().unwrap();
assert!(ptr_variadic_fn_abi.c_variadic);
assert_eq!(ptr_variadic_fn_abi.args.len(), 1);

ControlFlow::Continue(())
}

Expand Down Expand Up @@ -164,6 +179,14 @@ fn generate_input(path: &str) -> std::io::Result<()> {
pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) -> usize {{
0
}}
pub type ComplexFn = fn([u8; 0], char, NonZero<u8>) -> Result<usize, &'static str>;
pub type VariadicFn = unsafe extern "C" fn(usize, ...) -> usize;
pub fn fn_ptr_holder(complex_fn: ComplexFn, variadic_fn: VariadicFn) {{
// We only care about the signature.
todo!()
}}
"#
)?;
Ok(())
Expand Down

0 comments on commit 225796a

Please sign in to comment.