@@ -15,6 +15,8 @@ use memory::Pointer;
15
15
use value:: PrimVal ;
16
16
use value:: Value ;
17
17
18
+ use std:: str:: from_utf8;
19
+
18
20
mod intrinsic;
19
21
20
22
impl < ' a , ' tcx > EvalContext < ' a , ' tcx > {
@@ -200,14 +202,37 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
200
202
Abi :: RustIntrinsic => {
201
203
let ty = fn_ty. sig . 0 . output ( ) ;
202
204
let layout = self . type_layout ( ty) ?;
203
- let ( ret, target) = destination. unwrap ( ) ;
205
+ let ( ret, target) = match destination {
206
+ Some ( dest) => dest,
207
+ None => {
208
+ assert_eq ! ( & self . tcx. item_name( def_id) . as_str( ) [ ..] , "abort" ) ;
209
+ return Err ( EvalError :: Abort ) ;
210
+ }
211
+ } ;
204
212
self . call_intrinsic ( def_id, substs, arg_operands, ret, ty, layout, target) ?;
205
213
Ok ( ( ) )
206
214
}
207
215
208
216
Abi :: C => {
209
217
let ty = fn_ty. sig . 0 . output ( ) ;
210
- let ( ret, target) = destination. unwrap ( ) ;
218
+ let ( ret, target) = match destination {
219
+ Some ( dest) => dest,
220
+ None => {
221
+ assert_eq ! ( & self . tcx. item_name( def_id) . as_str( ) [ ..] , "panic_impl" ) ;
222
+ let args_res: EvalResult < Vec < Value > > = arg_operands. iter ( )
223
+ . map ( |arg| self . eval_operand ( arg) ?. ok_or ( EvalError :: ReadUndefBytes ) )
224
+ . collect ( ) ;
225
+ let args = args_res?;
226
+ // FIXME: process panic text
227
+ let file_slice = args[ 1 ] . expect_slice ( & self . memory ) ?;
228
+ let file = from_utf8 ( self . memory . read_bytes ( file_slice. 0 , file_slice. 1 ) ?)
229
+ . expect ( "panic message not utf8" )
230
+ . to_owned ( ) ;
231
+ let u32 = self . tcx . types . u32 ;
232
+ let line = self . value_to_primval ( args[ 2 ] , u32) ?. to_u64 ( ) as u32 ;
233
+ return Err ( EvalError :: Panic { file : file, line : line } ) ;
234
+ }
235
+ } ;
211
236
self . call_c_abi ( def_id, arg_operands, ret, ty) ?;
212
237
self . goto_block ( target) ;
213
238
Ok ( ( ) )
@@ -358,6 +383,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
358
383
let args = args_res?;
359
384
360
385
let usize = self . tcx . types . usize ;
386
+ let i32 = self . tcx . types . i32 ;
361
387
362
388
match & link_name[ ..] {
363
389
"__rust_allocate" => {
@@ -403,6 +429,18 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
403
429
self . write_primval ( dest, PrimVal :: new ( result as u64 ) , dest_ty) ?;
404
430
}
405
431
432
+ "memrchr" => {
433
+ let ptr = args[ 0 ] . read_ptr ( & self . memory ) ?;
434
+ let val = self . value_to_primval ( args[ 1 ] , usize) ?. to_u64 ( ) as u8 ;
435
+ let num = self . value_to_primval ( args[ 2 ] , usize) ?. to_u64 ( ) ;
436
+ if let Some ( idx) = self . memory . read_bytes ( ptr, num) ?. iter ( ) . rev ( ) . position ( |& c| c == val) {
437
+ let new_ptr = ptr. offset ( num - idx as u64 - 1 ) ;
438
+ self . write_value ( Value :: ByVal ( PrimVal :: from_ptr ( new_ptr) ) , dest, dest_ty) ?;
439
+ } else {
440
+ self . write_value ( Value :: ByVal ( PrimVal :: new ( 0 ) ) , dest, dest_ty) ?;
441
+ }
442
+ }
443
+
406
444
"memchr" => {
407
445
let ptr = args[ 0 ] . read_ptr ( & self . memory ) ?;
408
446
let val = self . value_to_primval ( args[ 1 ] , usize) ?. to_u64 ( ) as u8 ;
@@ -415,6 +453,27 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
415
453
}
416
454
}
417
455
456
+ "write" => {
457
+ // int filedes
458
+ let filedes = self . value_to_primval ( args[ 0 ] , usize) ?. to_u64 ( ) ;
459
+ // const void* buffer
460
+ let buffer = args[ 1 ] . read_ptr ( & self . memory ) ?;
461
+ // size_t size
462
+ let size = self . value_to_primval ( args[ 0 ] , usize) ?. to_u64 ( ) ;
463
+
464
+ {
465
+ let data = self . memory . read_bytes ( buffer, size) ?;
466
+ info ! ( "write to `{:x}`: {:?}" , filedes, data) ;
467
+ if filedes == 1 {
468
+ for & d in data {
469
+ print ! ( "{}" , d as char ) ;
470
+ }
471
+ }
472
+ }
473
+
474
+ self . write_primval ( dest, PrimVal :: new ( size as u64 ) , dest_ty) ?;
475
+ }
476
+
418
477
"getenv" => {
419
478
{
420
479
let name_ptr = args[ 0 ] . read_ptr ( & self . memory ) ?;
@@ -423,6 +482,31 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
423
482
}
424
483
self . write_value ( Value :: ByVal ( PrimVal :: new ( 0 ) ) , dest, dest_ty) ?;
425
484
}
485
+ "pthread_key_create" => {
486
+ // pthread_key_t* key
487
+ let key = args[ 0 ] . read_ptr ( & self . memory ) ?;
488
+ let pthread_key_t = self . tcx . types . i32 ;
489
+ self . next_pthread_key += 1 ;
490
+ let new_key = self . next_pthread_key ;
491
+ self . write_primval ( Lvalue :: from_ptr ( key) , PrimVal :: new ( new_key as u64 ) , pthread_key_t) ?;
492
+ self . write_primval ( dest, PrimVal :: new ( 0 ) , dest_ty) ?;
493
+ }
494
+
495
+ "pthread_setspecific" => {
496
+ let key = self . value_to_primval ( args[ 0 ] , i32) ?. to_u64 ( ) ;
497
+ let val = args[ 1 ] . read_ptr ( & self . memory ) ?;
498
+ assert_eq ! ( key as i32 as u64 , key) ;
499
+ self . pthread . insert ( key as i32 , val) ;
500
+ // FIXME: only keys that were created should exist
501
+ self . write_primval ( dest, PrimVal :: new ( 0 ) , dest_ty) ?;
502
+ }
503
+
504
+ "pthread_getspecific" => {
505
+ let key = self . value_to_primval ( args[ 0 ] , i32) ?. to_u64 ( ) ;
506
+ assert_eq ! ( key as i32 as u64 , key) ;
507
+ let val = self . pthread . get ( & ( key as i32 ) ) . map ( |& p| p) . unwrap_or ( Pointer :: from_int ( 0 ) ) ;
508
+ self . write_primval ( dest, PrimVal :: from_ptr ( val) , dest_ty) ?;
509
+ }
426
510
427
511
// unix panic code inside libstd will read the return value of this function
428
512
"pthread_rwlock_rdlock" => {
0 commit comments