diff --git a/src/shims/native_lib/mod.rs b/src/shims/native_lib/mod.rs index 382839ea1e..483da4b67b 100644 --- a/src/shims/native_lib/mod.rs +++ b/src/shims/native_lib/mod.rs @@ -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::(fun, libffi_args) }; Scalar::from_target_usize(x.try_into().unwrap(), this) } + ty::Float(FloatTy::F32) => { + let x = unsafe { ffi::call::(fun, libffi_args) }; + Scalar::from_f32(x.to_soft()) + } + ty::Float(FloatTy::F64) => { + let x = unsafe { ffi::call::(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!( diff --git a/tests/native-lib/pass/scalar_arguments.rs b/tests/native-lib/pass/scalar_arguments.rs index 9e99977a69..231df67bb5 100644 --- a/tests/native-lib/pass/scalar_arguments.rs +++ b/tests/native-lib/pass/scalar_arguments.rs @@ -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(); } diff --git a/tests/native-lib/scalar_arguments.c b/tests/native-lib/scalar_arguments.c index 8cf38f7441..10b6244bde 100644 --- a/tests/native-lib/scalar_arguments.c +++ b/tests/native-lib/scalar_arguments.c @@ -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;