@@ -3,8 +3,11 @@ use std::ops::Deref;
3
3
4
4
use libffi:: high:: call as ffi;
5
5
use libffi:: low:: CodePtr ;
6
- use rustc_abi:: { BackendRepr , HasDataLayout } ;
7
- use rustc_middle:: ty:: { self as ty, IntTy , UintTy } ;
6
+ use rustc_abi:: { BackendRepr , HasDataLayout , Size } ;
7
+ use rustc_middle:: {
8
+ mir:: interpret:: Pointer ,
9
+ ty:: { self as ty, IntTy , UintTy } ,
10
+ } ;
8
11
use rustc_span:: Symbol ;
9
12
10
13
use crate :: * ;
@@ -75,6 +78,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
75
78
unsafe { ffi:: call :: < ( ) > ( ptr, libffi_args. as_slice ( ) ) } ;
76
79
return interp_ok ( ImmTy :: uninit ( dest. layout ) ) ;
77
80
}
81
+ ty:: RawPtr ( ..) => {
82
+ let x = unsafe { ffi:: call :: < * const ( ) > ( ptr, libffi_args. as_slice ( ) ) } ;
83
+ let ptr = Pointer :: new ( Provenance :: Wildcard , Size :: from_bytes ( x. addr ( ) ) ) ;
84
+ Scalar :: from_pointer ( ptr, this)
85
+ }
78
86
_ => throw_unsup_format ! ( "unsupported return type for native call: {:?}" , link_name) ,
79
87
} ;
80
88
interp_ok ( ImmTy :: from_scalar ( scalar, dest. layout ) )
@@ -152,8 +160,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
152
160
if !matches ! ( arg. layout. backend_repr, BackendRepr :: Scalar ( _) ) {
153
161
throw_unsup_format ! ( "only scalar argument types are support for native calls" )
154
162
}
155
- libffi_args. push ( imm_to_carg ( this. read_immediate ( arg) ?, this) ?) ;
163
+ let imm = this. read_immediate ( arg) ?;
164
+ libffi_args. push ( imm_to_carg ( & imm, this) ?) ;
165
+ // If we are passing a pointer, prepare the memory it points to.
166
+ if matches ! ( arg. layout. ty. kind( ) , ty:: RawPtr ( ..) ) {
167
+ let ptr = imm. to_scalar ( ) . to_pointer ( this) ?;
168
+ let Some ( prov) = ptr. provenance else {
169
+ // Pointer without provenance may not access any memory.
170
+ continue ;
171
+ } ;
172
+ // We use `get_alloc_id` for its best-effort behaviour with Wildcard provenance.
173
+ let Some ( alloc_id) = prov. get_alloc_id ( ) else {
174
+ // Wildcard pointer, whatever it points to must be already exposed.
175
+ continue ;
176
+ } ;
177
+ this. prepare_for_native_call ( alloc_id, prov) ?;
178
+ }
156
179
}
180
+
181
+ // FIXME: In the future, we should also call `prepare_for_native_call` on all previously
182
+ // exposed allocations, since C may access any of them.
157
183
158
184
// Convert them to `libffi::high::Arg` type.
159
185
let libffi_args = libffi_args
@@ -220,7 +246,7 @@ impl<'a> CArg {
220
246
221
247
/// Extract the scalar value from the result of reading a scalar from the machine,
222
248
/// and convert it to a `CArg`.
223
- fn imm_to_carg < ' tcx > ( v : ImmTy < ' tcx > , cx : & impl HasDataLayout ) -> InterpResult < ' tcx , CArg > {
249
+ fn imm_to_carg < ' tcx > ( v : & ImmTy < ' tcx > , cx : & impl HasDataLayout ) -> InterpResult < ' tcx , CArg > {
224
250
interp_ok ( match v. layout . ty . kind ( ) {
225
251
// If the primitive provided can be converted to a type matching the type pattern
226
252
// then create a `CArg` of this primitive value with the corresponding `CArg` constructor.
@@ -238,18 +264,10 @@ fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'t
238
264
ty:: Uint ( UintTy :: U64 ) => CArg :: UInt64 ( v. to_scalar ( ) . to_u64 ( ) ?) ,
239
265
ty:: Uint ( UintTy :: Usize ) =>
240
266
CArg :: USize ( v. to_scalar ( ) . to_target_usize ( cx) ?. try_into ( ) . unwrap ( ) ) ,
241
- ty:: RawPtr ( _, mutability) => {
242
- // Arbitrary mutable pointer accesses are not currently supported in Miri.
243
- if mutability. is_mut ( ) {
244
- throw_unsup_format ! (
245
- "unsupported mutable pointer type for native call: {}" ,
246
- v. layout. ty
247
- ) ;
248
- } else {
249
- let s = v. to_scalar ( ) . to_pointer ( cx) ?. addr ( ) ;
250
- // This relies on the `expose_provenance` in `addr_from_alloc_id`.
251
- CArg :: RawPtr ( std:: ptr:: with_exposed_provenance_mut ( s. bytes_usize ( ) ) )
252
- }
267
+ ty:: RawPtr ( ..) => {
268
+ let s = v. to_scalar ( ) . to_pointer ( cx) ?. addr ( ) ;
269
+ // This relies on the `expose_provenance` in `addr_from_alloc_id`.
270
+ CArg :: RawPtr ( std:: ptr:: with_exposed_provenance_mut ( s. bytes_usize ( ) ) )
253
271
}
254
272
_ => throw_unsup_format ! ( "unsupported argument type for native call: {}" , v. layout. ty) ,
255
273
} )
0 commit comments