Merge pull request #4650 from FranciscoTGouveia/f32/64-native-func-calls

Support `f32`/`f64` in native function calls
This commit is contained in:
Ralf Jung 2025-10-28 10:23:33 +00:00 committed by GitHub
commit 8fef16e2a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 22 additions and 2 deletions

View file

@ -8,10 +8,12 @@ use libffi::middle::Type as FfiType;
use rustc_abi::{HasDataLayout, Size};
use rustc_data_structures::either;
use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout};
use rustc_middle::ty::{self, IntTy, Ty, UintTy};
use rustc_middle::ty::{self, FloatTy, IntTy, Ty, UintTy};
use rustc_span::Symbol;
use serde::{Deserialize, Serialize};
use self::helpers::ToSoft;
mod ffi;
#[cfg_attr(
@ -138,6 +140,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
let x = unsafe { ffi::call::<usize>(fun, libffi_args) };
Scalar::from_target_usize(x.try_into().unwrap(), this)
}
ty::Float(FloatTy::F32) => {
let x = unsafe { ffi::call::<f32>(fun, libffi_args) };
Scalar::from_f32(x.to_soft())
}
ty::Float(FloatTy::F64) => {
let x = unsafe { ffi::call::<f64>(fun, libffi_args) };
Scalar::from_f64(x.to_soft())
}
// Functions with no declared return type (i.e., the default return)
// have the output_type `Tuple([])`.
ty::Tuple(t_list) if (*t_list).deref().is_empty() => {
@ -396,7 +406,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
/// Gets the matching libffi type for a given Ty.
fn ty_to_ffitype(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, FfiType> {
use rustc_abi::{AddressSpace, BackendRepr, Integer, Primitive};
use rustc_abi::{AddressSpace, BackendRepr, Float, Integer, Primitive};
// `BackendRepr::Scalar` is also a signal to pass this type as a scalar in the ABI. This
// matches what codegen does. This does mean that we support some types whose ABI is not
@ -413,6 +423,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
Primitive::Int(Integer::I16, /* signed */ false) => FfiType::u16(),
Primitive::Int(Integer::I32, /* signed */ false) => FfiType::u32(),
Primitive::Int(Integer::I64, /* signed */ false) => FfiType::u64(),
Primitive::Float(Float::F32) => FfiType::f32(),
Primitive::Float(Float::F64) => FfiType::f64(),
Primitive::Pointer(AddressSpace::ZERO) => FfiType::pointer(),
_ =>
throw_unsup_format!(

View file

@ -17,6 +17,7 @@ extern "C" {
) -> i32;
fn add_short_to_long(x: i16, y: i64) -> i64;
fn get_unsigned_int() -> u32;
fn add_float(x: f32) -> f32;
fn printer();
}
@ -37,6 +38,9 @@ fn main() {
// test function that returns -10 as an unsigned int
assert_eq!(get_unsigned_int(), (-10i32) as u32);
// test function that adds 1.5 to a f32
assert_eq!(add_float(1.0f32), 2.5f32);
// test void function that prints from C
printer();
}

View file

@ -30,6 +30,10 @@ EXPORT int64_t add_short_to_long(int16_t x, int64_t y) {
return x + y;
}
EXPORT float add_float(float x) {
return x + 1.5f;
}
// To test that functions not marked with EXPORT cannot be called by Miri.
int32_t not_exported(void) {
return 0;