@@ -90,7 +90,16 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
90
90
ty:: TyFnPtr ( bare_fn_ty) => {
91
91
let fn_ptr = self . eval_operand_to_primval ( func) ?. to_ptr ( ) ;
92
92
let ( def_id, substs, abi, sig) = self . memory . get_fn ( fn_ptr. alloc_id ) ?;
93
- if abi != bare_fn_ty. abi || sig != bare_fn_ty. sig . skip_binder ( ) {
93
+ let bare_sig = self . tcx . erase_late_bound_regions_and_normalize ( & bare_fn_ty. sig ) ;
94
+ let bare_sig = self . tcx . erase_regions ( & bare_sig) ;
95
+ // transmuting function pointers in miri is fine as long as the number of
96
+ // arguments and the abi don't change.
97
+ // FIXME: also check the size of the arguments' type and the return type
98
+ // Didn't get it to work, since that triggers an assertion in rustc which
99
+ // checks whether the type has escaping regions
100
+ if abi != bare_fn_ty. abi ||
101
+ sig. variadic != bare_sig. variadic ||
102
+ sig. inputs ( ) . len ( ) != bare_sig. inputs ( ) . len ( ) {
94
103
return Err ( EvalError :: FunctionPointerTyMismatch ( abi, sig, bare_fn_ty) ) ;
95
104
}
96
105
self . eval_fn_call ( def_id, substs, bare_fn_ty, destination, args,
@@ -189,15 +198,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
189
198
use syntax:: abi:: Abi ;
190
199
match fn_ty. abi {
191
200
Abi :: RustIntrinsic => {
192
- let ty = fn_ty. sig . 0 . output ;
201
+ let ty = fn_ty. sig . 0 . output ( ) ;
193
202
let layout = self . type_layout ( ty) ?;
194
203
let ( ret, target) = destination. unwrap ( ) ;
195
204
self . call_intrinsic ( def_id, substs, arg_operands, ret, ty, layout, target) ?;
196
205
Ok ( ( ) )
197
206
}
198
207
199
208
Abi :: C => {
200
- let ty = fn_ty. sig . 0 . output ;
209
+ let ty = fn_ty. sig . 0 . output ( ) ;
201
210
let ( ret, target) = destination. unwrap ( ) ;
202
211
self . call_c_abi ( def_id, arg_operands, ret, ty) ?;
203
212
self . goto_block ( target) ;
@@ -320,11 +329,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
320
329
. collect ( ) ;
321
330
let args = args_res?;
322
331
323
- if link_name. starts_with ( "pthread_" ) {
324
- warn ! ( "ignoring C ABI call: {}" , link_name) ;
325
- return Ok ( ( ) ) ;
326
- }
327
-
328
332
let usize = self . tcx . types . usize ;
329
333
330
334
match & link_name[ ..] {
@@ -371,6 +375,37 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
371
375
self . write_primval ( dest, PrimVal :: new ( result as u64 ) , dest_ty) ?;
372
376
}
373
377
378
+ "memchr" => {
379
+ let ptr = args[ 0 ] . read_ptr ( & self . memory ) ?;
380
+ let val = self . value_to_primval ( args[ 1 ] , usize) ?. to_u64 ( ) as u8 ;
381
+ let num = self . value_to_primval ( args[ 2 ] , usize) ?. to_u64 ( ) ;
382
+ if let Some ( idx) = self . memory . read_bytes ( ptr, num) ?. iter ( ) . position ( |& c| c == val) {
383
+ let new_ptr = ptr. offset ( idx as u64 ) ;
384
+ self . write_value ( Value :: ByVal ( PrimVal :: from_ptr ( new_ptr) ) , dest, dest_ty) ?;
385
+ } else {
386
+ self . write_value ( Value :: ByVal ( PrimVal :: new ( 0 ) ) , dest, dest_ty) ?;
387
+ }
388
+ }
389
+
390
+ "getenv" => {
391
+ {
392
+ let name_ptr = args[ 0 ] . read_ptr ( & self . memory ) ?;
393
+ let name = self . memory . read_c_str ( name_ptr) ?;
394
+ info ! ( "ignored env var request for `{:?}`" , :: std:: str :: from_utf8( name) ) ;
395
+ }
396
+ self . write_value ( Value :: ByVal ( PrimVal :: new ( 0 ) ) , dest, dest_ty) ?;
397
+ }
398
+
399
+ // unix panic code inside libstd will read the return value of this function
400
+ "pthread_rwlock_rdlock" => {
401
+ self . write_primval ( dest, PrimVal :: new ( 0 ) , dest_ty) ?;
402
+ }
403
+
404
+ link_name if link_name. starts_with ( "pthread_" ) => {
405
+ warn ! ( "ignoring C ABI call: {}" , link_name) ;
406
+ return Ok ( ( ) ) ;
407
+ } ,
408
+
374
409
_ => {
375
410
return Err ( EvalError :: Unimplemented ( format ! ( "can't call C ABI function: {}" , link_name) ) ) ;
376
411
}
@@ -520,7 +555,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
520
555
let offset = idx * self . memory . pointer_size ( ) ;
521
556
let fn_ptr = self . memory . read_ptr ( vtable. offset ( offset) ) ?;
522
557
let ( def_id, substs, _abi, sig) = self . memory . get_fn ( fn_ptr. alloc_id ) ?;
523
- * first_ty = sig. inputs [ 0 ] ;
558
+ * first_ty = sig. inputs ( ) [ 0 ] ;
524
559
Ok ( ( def_id, substs, Vec :: new ( ) ) )
525
560
} else {
526
561
Err ( EvalError :: VtableForArgumentlessMethod )
@@ -664,7 +699,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
664
699
// some values don't need to call a drop impl, so the value is null
665
700
if drop_fn != Pointer :: from_int ( 0 ) {
666
701
let ( def_id, substs, _abi, sig) = self . memory . get_fn ( drop_fn. alloc_id ) ?;
667
- let real_ty = sig. inputs [ 0 ] ;
702
+ let real_ty = sig. inputs ( ) [ 0 ] ;
668
703
self . drop ( Lvalue :: from_ptr ( ptr) , real_ty, drop) ?;
669
704
drop. push ( ( def_id, Value :: ByVal ( PrimVal :: from_ptr ( ptr) ) , substs) ) ;
670
705
} else {
0 commit comments