]> git.lizzy.rs Git - rust.git/blob - miri/fn_call.rs
3ca71e9b90c20824860d49ae27324ea4f4db98d7
[rust.git] / miri / fn_call.rs
1 use rustc::ty::{self, Ty};
2 use rustc::ty::layout::LayoutOf;
3 use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
4 use rustc::mir;
5 use syntax::attr;
6 use syntax::abi::Abi;
7 use syntax::codemap::Span;
8
9 use std::mem;
10
11 use rustc::traits;
12
13 use super::*;
14
15 use tls::MemoryExt;
16
17 use super::memory::MemoryKind;
18
19 pub trait EvalContextExt<'tcx> {
20     fn call_c_abi(
21         &mut self,
22         def_id: DefId,
23         args: &[ValTy<'tcx>],
24         dest: Place,
25         dest_ty: Ty<'tcx>,
26         dest_block: mir::BasicBlock,
27     ) -> EvalResult<'tcx>;
28
29     fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>>;
30
31     fn call_missing_fn(
32         &mut self,
33         instance: ty::Instance<'tcx>,
34         destination: Option<(Place, mir::BasicBlock)>,
35         args: &[ValTy<'tcx>],
36         sig: ty::FnSig<'tcx>,
37         path: String,
38     ) -> EvalResult<'tcx>;
39
40     fn eval_fn_call(
41         &mut self,
42         instance: ty::Instance<'tcx>,
43         destination: Option<(Place, mir::BasicBlock)>,
44         args: &[ValTy<'tcx>],
45         span: Span,
46         sig: ty::FnSig<'tcx>,
47     ) -> EvalResult<'tcx, bool>;
48
49     fn write_null(&mut self, dest: Place, dest_ty: Ty<'tcx>) -> EvalResult<'tcx>;
50 }
51
52 impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'tcx>> {
53     fn eval_fn_call(
54         &mut self,
55         instance: ty::Instance<'tcx>,
56         destination: Option<(Place, mir::BasicBlock)>,
57         args: &[ValTy<'tcx>],
58         span: Span,
59         sig: ty::FnSig<'tcx>,
60     ) -> EvalResult<'tcx, bool> {
61         trace!("eval_fn_call: {:#?}, {:#?}", instance, destination);
62
63         let mir = match self.load_mir(instance.def) {
64             Ok(mir) => mir,
65             Err(EvalError { kind: EvalErrorKind::NoMirFor(path), .. }) => {
66                 self.call_missing_fn(
67                     instance,
68                     destination,
69                     args,
70                     sig,
71                     path,
72                 )?;
73                 return Ok(true);
74             }
75             Err(other) => return Err(other),
76         };
77
78         let (return_place, return_to_block) = match destination {
79             Some((place, block)) => (place, StackPopCleanup::Goto(block)),
80             None => (Place::undef(), StackPopCleanup::None),
81         };
82
83         self.push_stack_frame(
84             instance,
85             span,
86             mir,
87             return_place,
88             return_to_block,
89         )?;
90
91         Ok(false)
92     }
93
94     fn call_c_abi(
95         &mut self,
96         def_id: DefId,
97         args: &[ValTy<'tcx>],
98         dest: Place,
99         dest_ty: Ty<'tcx>,
100         dest_block: mir::BasicBlock,
101     ) -> EvalResult<'tcx> {
102         let attrs = self.tcx.get_attrs(def_id);
103         let link_name = match attr::first_attr_value_str_by_name(&attrs, "link_name") {
104             Some(name) => name.as_str(),
105             None => self.tcx.item_name(def_id),
106         };
107
108         match &link_name[..] {
109             "malloc" => {
110                 let size = self.value_to_primval(args[0])?.to_u64()?;
111                 if size == 0 {
112                     self.write_null(dest, dest_ty)?;
113                 } else {
114                     let align = self.memory.pointer_size();
115                     let ptr = self.memory.allocate(size, align, Some(MemoryKind::C.into()))?;
116                     self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
117                 }
118             }
119
120             "free" => {
121                 let ptr = self.into_ptr(args[0].value)?;
122                 if !ptr.is_null()? {
123                     self.memory.deallocate(
124                         ptr.to_ptr()?,
125                         None,
126                         MemoryKind::C.into(),
127                     )?;
128                 }
129             }
130
131             "syscall" => {
132                 // TODO: read `syscall` ids like `sysconf` ids and
133                 // figure out some way to actually process some of them
134                 //
135                 // libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)
136                 // is called if a `HashMap` is created the regular way.
137                 match self.value_to_primval(args[0])?.to_u64()? {
138                     318 | 511 => {
139                         return err!(Unimplemented(
140                             "miri does not support random number generators".to_owned(),
141                         ))
142                     }
143                     id => {
144                         return err!(Unimplemented(
145                             format!("miri does not support syscall id {}", id),
146                         ))
147                     }
148                 }
149             }
150
151             "dlsym" => {
152                 let _handle = self.into_ptr(args[0].value)?;
153                 let symbol = self.into_ptr(args[1].value)?.to_ptr()?;
154                 let symbol_name = self.memory.read_c_str(symbol)?;
155                 let err = format!("bad c unicode symbol: {:?}", symbol_name);
156                 let symbol_name = ::std::str::from_utf8(symbol_name).unwrap_or(&err);
157                 return err!(Unimplemented(format!(
158                     "miri does not support dynamically loading libraries (requested symbol: {})",
159                     symbol_name
160                 )));
161             }
162
163             "__rust_maybe_catch_panic" => {
164                 // fn __rust_maybe_catch_panic(f: fn(*mut u8), data: *mut u8, data_ptr: *mut usize, vtable_ptr: *mut usize) -> u32
165                 // We abort on panic, so not much is going on here, but we still have to call the closure
166                 let u8_ptr_ty = self.tcx.mk_mut_ptr(self.tcx.types.u8);
167                 let f = self.into_ptr(args[0].value)?.to_ptr()?;
168                 let data = self.into_ptr(args[1].value)?;
169                 let f_instance = self.memory.get_fn(f)?;
170                 self.write_null(dest, dest_ty)?;
171
172                 // Now we make a function call.  TODO: Consider making this re-usable?  EvalContext::step does sth. similar for the TLS dtors,
173                 // and of course eval_main.
174                 let mir = self.load_mir(f_instance.def)?;
175                 self.push_stack_frame(
176                     f_instance,
177                     mir.span,
178                     mir,
179                     Place::undef(),
180                     StackPopCleanup::Goto(dest_block),
181                 )?;
182                 let mut args = self.frame().mir.args_iter();
183
184                 let arg_local = args.next().ok_or(
185                     EvalErrorKind::AbiViolation(
186                         "Argument to __rust_maybe_catch_panic does not take enough arguments."
187                             .to_owned(),
188                     ),
189                 )?;
190                 let arg_dest = self.eval_place(&mir::Place::Local(arg_local))?;
191                 self.write_ptr(arg_dest, data, u8_ptr_ty)?;
192
193                 assert!(args.next().is_none(), "__rust_maybe_catch_panic argument has more arguments than expected");
194
195                 // We ourselves return 0
196                 self.write_null(dest, dest_ty)?;
197
198                 // Don't fall through
199                 return Ok(());
200             }
201
202             "__rust_start_panic" => {
203                 return err!(Panic);
204             }
205
206             "memcmp" => {
207                 let left = self.into_ptr(args[0].value)?;
208                 let right = self.into_ptr(args[1].value)?;
209                 let n = self.value_to_primval(args[2])?.to_u64()?;
210
211                 let result = {
212                     let left_bytes = self.memory.read_bytes(left, n)?;
213                     let right_bytes = self.memory.read_bytes(right, n)?;
214
215                     use std::cmp::Ordering::*;
216                     match left_bytes.cmp(right_bytes) {
217                         Less => -1i8,
218                         Equal => 0,
219                         Greater => 1,
220                     }
221                 };
222
223                 self.write_primval(
224                     dest,
225                     PrimVal::Bytes(result as u128),
226                     dest_ty,
227                 )?;
228             }
229
230             "memrchr" => {
231                 let ptr = self.into_ptr(args[0].value)?;
232                 let val = self.value_to_primval(args[1])?.to_u64()? as u8;
233                 let num = self.value_to_primval(args[2])?.to_u64()?;
234                 if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().rev().position(
235                     |&c| c == val,
236                 )
237                 {
238                     let new_ptr = ptr.offset(num - idx as u64 - 1, &self)?;
239                     self.write_ptr(dest, new_ptr, dest_ty)?;
240                 } else {
241                     self.write_null(dest, dest_ty)?;
242                 }
243             }
244
245             "memchr" => {
246                 let ptr = self.into_ptr(args[0].value)?;
247                 let val = self.value_to_primval(args[1])?.to_u64()? as u8;
248                 let num = self.value_to_primval(args[2])?.to_u64()?;
249                 if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().position(
250                     |&c| c == val,
251                 )
252                 {
253                     let new_ptr = ptr.offset(idx as u64, &self)?;
254                     self.write_ptr(dest, new_ptr, dest_ty)?;
255                 } else {
256                     self.write_null(dest, dest_ty)?;
257                 }
258             }
259
260             "getenv" => {
261                 let result = {
262                     let name_ptr = self.into_ptr(args[0].value)?.to_ptr()?;
263                     let name = self.memory.read_c_str(name_ptr)?;
264                     match self.machine.env_vars.get(name) {
265                         Some(&var) => PrimVal::Ptr(var),
266                         None => PrimVal::Bytes(0),
267                     }
268                 };
269                 self.write_primval(dest, result, dest_ty)?;
270             }
271
272             "unsetenv" => {
273                 let mut success = None;
274                 {
275                     let name_ptr = self.into_ptr(args[0].value)?;
276                     if !name_ptr.is_null()? {
277                         let name = self.memory.read_c_str(name_ptr.to_ptr()?)?;
278                         if !name.is_empty() && !name.contains(&b'=') {
279                             success = Some(self.machine.env_vars.remove(name));
280                         }
281                     }
282                 }
283                 if let Some(old) = success {
284                     if let Some(var) = old {
285                         self.memory.deallocate(var, None, MemoryKind::Env.into())?;
286                     }
287                     self.write_null(dest, dest_ty)?;
288                 } else {
289                     self.write_primval(dest, PrimVal::from_i128(-1), dest_ty)?;
290                 }
291             }
292
293             "setenv" => {
294                 let mut new = None;
295                 {
296                     let name_ptr = self.into_ptr(args[0].value)?;
297                     let value_ptr = self.into_ptr(args[1].value)?.to_ptr()?;
298                     let value = self.memory.read_c_str(value_ptr)?;
299                     if !name_ptr.is_null()? {
300                         let name = self.memory.read_c_str(name_ptr.to_ptr()?)?;
301                         if !name.is_empty() && !name.contains(&b'=') {
302                             new = Some((name.to_owned(), value.to_owned()));
303                         }
304                     }
305                 }
306                 if let Some((name, value)) = new {
307                     // +1 for the null terminator
308                     let value_copy = self.memory.allocate(
309                         (value.len() + 1) as u64,
310                         1,
311                         Some(MemoryKind::Env.into()),
312                     )?;
313                     self.memory.write_bytes(value_copy.into(), &value)?;
314                     let trailing_zero_ptr = value_copy.offset(value.len() as u64, &self)?.into();
315                     self.memory.write_bytes(trailing_zero_ptr, &[0])?;
316                     if let Some(var) = self.machine.env_vars.insert(
317                         name.to_owned(),
318                         value_copy,
319                     )
320                     {
321                         self.memory.deallocate(var, None, MemoryKind::Env.into())?;
322                     }
323                     self.write_null(dest, dest_ty)?;
324                 } else {
325                     self.write_primval(dest, PrimVal::from_i128(-1), dest_ty)?;
326                 }
327             }
328
329             "write" => {
330                 let fd = self.value_to_primval(args[0])?.to_u64()?;
331                 let buf = self.into_ptr(args[1].value)?;
332                 let n = self.value_to_primval(args[2])?.to_u64()?;
333                 trace!("Called write({:?}, {:?}, {:?})", fd, buf, n);
334                 let result = if fd == 1 || fd == 2 {
335                     // stdout/stderr
336                     use std::io::{self, Write};
337
338                     let buf_cont = self.memory.read_bytes(buf, n)?;
339                     let res = if fd == 1 {
340                         io::stdout().write(buf_cont)
341                     } else {
342                         io::stderr().write(buf_cont)
343                     };
344                     match res {
345                         Ok(n) => n as isize,
346                         Err(_) => -1,
347                     }
348                 } else {
349                     warn!("Ignored output to FD {}", fd);
350                     n as isize // pretend it all went well
351                 }; // now result is the value we return back to the program
352                 self.write_primval(
353                     dest,
354                     PrimVal::Bytes(result as u128),
355                     dest_ty,
356                 )?;
357             }
358
359             "strlen" => {
360                 let ptr = self.into_ptr(args[0].value)?.to_ptr()?;
361                 let n = self.memory.read_c_str(ptr)?.len();
362                 self.write_primval(dest, PrimVal::Bytes(n as u128), dest_ty)?;
363             }
364
365             // Some things needed for sys::thread initialization to go through
366             "signal" | "sigaction" | "sigaltstack" => {
367                 self.write_primval(dest, PrimVal::Bytes(0), dest_ty)?;
368             }
369
370             "sysconf" => {
371                 let name = self.value_to_primval(args[0])?.to_u64()?;
372                 trace!("sysconf() called with name {}", name);
373                 // cache the sysconf integers via miri's global cache
374                 let paths = &[
375                     (&["libc", "_SC_PAGESIZE"], PrimVal::Bytes(4096)),
376                     (&["libc", "_SC_GETPW_R_SIZE_MAX"], PrimVal::from_i128(-1)),
377                 ];
378                 let mut result = None;
379                 for &(path, path_value) in paths {
380                     if let Ok(instance) = self.resolve_path(path) {
381                         let cid = GlobalId {
382                             instance,
383                             promoted: None,
384                         };
385                         // compute global if not cached
386                         let val = match self.tcx.interpret_interner.borrow().get_cached(cid) {
387                             Some(ptr) => ptr,
388                             None => eval_body(self.tcx, instance, ty::ParamEnv::empty(traits::Reveal::All))?.0,
389                         };
390                         let val = self.value_to_primval(ValTy { value: Value::ByRef(val), ty: args[0].ty })?.to_u64()?;
391                         if val == name {
392                             result = Some(path_value);
393                             break;
394                         }
395                     }
396                 }
397                 if let Some(result) = result {
398                     self.write_primval(dest, result, dest_ty)?;
399                 } else {
400                     return err!(Unimplemented(
401                         format!("Unimplemented sysconf name: {}", name),
402                     ));
403                 }
404             }
405
406             // Hook pthread calls that go to the thread-local storage memory subsystem
407             "pthread_key_create" => {
408                 let key_ptr = self.into_ptr(args[0].value)?;
409
410                 // Extract the function type out of the signature (that seems easier than constructing it ourselves...)
411                 let dtor = match self.into_ptr(args[1].value)?.into_inner_primval() {
412                     PrimVal::Ptr(dtor_ptr) => Some(self.memory.get_fn(dtor_ptr)?),
413                     PrimVal::Bytes(0) => None,
414                     PrimVal::Bytes(_) => return err!(ReadBytesAsPointer),
415                     PrimVal::Undef => return err!(ReadUndefBytes),
416                 };
417
418                 // Figure out how large a pthread TLS key actually is. This is libc::pthread_key_t.
419                 let key_type = args[0].ty.builtin_deref(true, ty::LvaluePreference::NoPreference)
420                                    .ok_or(EvalErrorKind::AbiViolation("Wrong signature used for pthread_key_create: First argument must be a raw pointer.".to_owned()))?.ty;
421                 let key_size = self.layout_of(key_type)?.size;
422
423                 // Create key and write it into the memory where key_ptr wants it
424                 let key = self.memory.create_tls_key(dtor) as u128;
425                 if key_size.bits() < 128 && key >= (1u128 << key_size.bits() as u128) {
426                     return err!(OutOfTls);
427                 }
428                 self.memory.write_primval(
429                     key_ptr.to_ptr()?,
430                     PrimVal::Bytes(key),
431                     key_size.bytes(),
432                     false,
433                 )?;
434
435                 // Return success (0)
436                 self.write_null(dest, dest_ty)?;
437             }
438             "pthread_key_delete" => {
439                 // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t
440                 let key = self.value_to_primval(args[0])?.to_u64()? as TlsKey;
441                 self.memory.delete_tls_key(key)?;
442                 // Return success (0)
443                 self.write_null(dest, dest_ty)?;
444             }
445             "pthread_getspecific" => {
446                 // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t
447                 let key = self.value_to_primval(args[0])?.to_u64()? as TlsKey;
448                 let ptr = self.memory.load_tls(key)?;
449                 self.write_ptr(dest, ptr, dest_ty)?;
450             }
451             "pthread_setspecific" => {
452                 // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t
453                 let key = self.value_to_primval(args[0])?.to_u64()? as TlsKey;
454                 let new_ptr = self.into_ptr(args[1].value)?;
455                 self.memory.store_tls(key, new_ptr)?;
456
457                 // Return success (0)
458                 self.write_null(dest, dest_ty)?;
459             }
460
461             // Stub out all the other pthread calls to just return 0
462             link_name if link_name.starts_with("pthread_") => {
463                 info!("ignoring C ABI call: {}", link_name);
464                 self.write_null(dest, dest_ty)?;
465             }
466
467             _ => {
468                 return err!(Unimplemented(
469                     format!("can't call C ABI function: {}", link_name),
470                 ));
471             }
472         }
473
474         // Since we pushed no stack frame, the main loop will act
475         // as if the call just completed and it's returning to the
476         // current frame.
477         self.dump_local(dest);
478         self.goto_block(dest_block);
479         Ok(())
480     }
481
482     /// Get an instance for a path.
483     fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>> {
484         self.tcx
485             .crates()
486             .iter()
487             .find(|&&krate| self.tcx.original_crate_name(krate) == path[0])
488             .and_then(|krate| {
489                 let krate = DefId {
490                     krate: *krate,
491                     index: CRATE_DEF_INDEX,
492                 };
493                 let mut items = self.tcx.item_children(krate);
494                 let mut path_it = path.iter().skip(1).peekable();
495
496                 while let Some(segment) = path_it.next() {
497                     for item in mem::replace(&mut items, Default::default()).iter() {
498                         if item.ident.name == *segment {
499                             if path_it.peek().is_none() {
500                                 return Some(ty::Instance::mono(self.tcx, item.def.def_id()));
501                             }
502
503                             items = self.tcx.item_children(item.def.def_id());
504                             break;
505                         }
506                     }
507                 }
508                 None
509             })
510             .ok_or_else(|| {
511                 let path = path.iter().map(|&s| s.to_owned()).collect();
512                 EvalErrorKind::PathNotFound(path).into()
513             })
514     }
515
516     fn call_missing_fn(
517         &mut self,
518         instance: ty::Instance<'tcx>,
519         destination: Option<(Place, mir::BasicBlock)>,
520         args: &[ValTy<'tcx>],
521         sig: ty::FnSig<'tcx>,
522         path: String,
523     ) -> EvalResult<'tcx> {
524         // In some cases in non-MIR libstd-mode, not having a destination is legit.  Handle these early.
525         match &path[..] {
526             "std::panicking::rust_panic_with_hook" |
527             "core::panicking::panic_fmt::::panic_impl" |
528             "std::rt::begin_panic_fmt" => return err!(Panic),
529             _ => {}
530         }
531
532         let dest_ty = sig.output();
533         let (dest, dest_block) = destination.ok_or_else(
534             || EvalErrorKind::NoMirFor(path.clone()),
535         )?;
536
537         if sig.abi == Abi::C {
538             // An external C function
539             // TODO: That functions actually has a similar preamble to what follows here.  May make sense to
540             // unify these two mechanisms for "hooking into missing functions".
541             self.call_c_abi(
542                 instance.def_id(),
543                 args,
544                 dest,
545                 dest_ty,
546                 dest_block,
547             )?;
548             return Ok(());
549         }
550
551         match &path[..] {
552             // Allocators are magic.  They have no MIR, even when the rest of libstd does.
553             "alloc::heap::::__rust_alloc" => {
554                 let size = self.value_to_primval(args[0])?.to_u64()?;
555                 let align = self.value_to_primval(args[1])?.to_u64()?;
556                 if size == 0 {
557                     return err!(HeapAllocZeroBytes);
558                 }
559                 if !align.is_power_of_two() {
560                     return err!(HeapAllocNonPowerOfTwoAlignment(align));
561                 }
562                 let ptr = self.memory.allocate(size, align, Some(MemoryKind::Rust.into()))?;
563                 self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
564             }
565             "alloc::heap::::__rust_alloc_zeroed" => {
566                 let size = self.value_to_primval(args[0])?.to_u64()?;
567                 let align = self.value_to_primval(args[1])?.to_u64()?;
568                 if size == 0 {
569                     return err!(HeapAllocZeroBytes);
570                 }
571                 if !align.is_power_of_two() {
572                     return err!(HeapAllocNonPowerOfTwoAlignment(align));
573                 }
574                 let ptr = self.memory.allocate(size, align, Some(MemoryKind::Rust.into()))?;
575                 self.memory.write_repeat(ptr.into(), 0, size)?;
576                 self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
577             }
578             "alloc::heap::::__rust_dealloc" => {
579                 let ptr = self.into_ptr(args[0].value)?.to_ptr()?;
580                 let old_size = self.value_to_primval(args[1])?.to_u64()?;
581                 let align = self.value_to_primval(args[2])?.to_u64()?;
582                 if old_size == 0 {
583                     return err!(HeapAllocZeroBytes);
584                 }
585                 if !align.is_power_of_two() {
586                     return err!(HeapAllocNonPowerOfTwoAlignment(align));
587                 }
588                 self.memory.deallocate(
589                     ptr,
590                     Some((old_size, align)),
591                     MemoryKind::Rust.into(),
592                 )?;
593             }
594             "alloc::heap::::__rust_realloc" => {
595                 let ptr = self.into_ptr(args[0].value)?.to_ptr()?;
596                 let old_size = self.value_to_primval(args[1])?.to_u64()?;
597                 let old_align = self.value_to_primval(args[2])?.to_u64()?;
598                 let new_size = self.value_to_primval(args[3])?.to_u64()?;
599                 let new_align = self.value_to_primval(args[4])?.to_u64()?;
600                 if old_size == 0 || new_size == 0 {
601                     return err!(HeapAllocZeroBytes);
602                 }
603                 if !old_align.is_power_of_two() {
604                     return err!(HeapAllocNonPowerOfTwoAlignment(old_align));
605                 }
606                 if !new_align.is_power_of_two() {
607                     return err!(HeapAllocNonPowerOfTwoAlignment(new_align));
608                 }
609                 let new_ptr = self.memory.reallocate(
610                     ptr,
611                     old_size,
612                     old_align,
613                     new_size,
614                     new_align,
615                     MemoryKind::Rust.into(),
616                 )?;
617                 self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?;
618             }
619
620             // A Rust function is missing, which means we are running with MIR missing for libstd (or other dependencies).
621             // Still, we can make many things mostly work by "emulating" or ignoring some functions.
622             "std::io::_print" => {
623                 warn!(
624                     "Ignoring output.  To run programs that print, make sure you have a libstd with full MIR."
625                 );
626             }
627             "std::thread::Builder::new" => {
628                 return err!(Unimplemented("miri does not support threading".to_owned()))
629             }
630             "std::env::args" => {
631                 return err!(Unimplemented(
632                     "miri does not support program arguments".to_owned(),
633                 ))
634             }
635             "std::panicking::panicking" |
636             "std::rt::panicking" => {
637                 // we abort on panic -> `std::rt::panicking` always returns false
638                 let bool = self.tcx.types.bool;
639                 self.write_primval(dest, PrimVal::from_bool(false), bool)?;
640             }
641             "std::sys::imp::c::::AddVectoredExceptionHandler" |
642             "std::sys::imp::c::::SetThreadStackGuarantee" => {
643                 let usize = self.tcx.types.usize;
644                 // any non zero value works for the stdlib. This is just used for stackoverflows anyway
645                 self.write_primval(dest, PrimVal::Bytes(1), usize)?;
646             },
647             _ => return err!(NoMirFor(path)),
648         }
649
650         // Since we pushed no stack frame, the main loop will act
651         // as if the call just completed and it's returning to the
652         // current frame.
653         self.dump_local(dest);
654         self.goto_block(dest_block);
655         return Ok(());
656     }
657
658     fn write_null(&mut self, dest: Place, dest_ty: Ty<'tcx>) -> EvalResult<'tcx> {
659         self.write_primval(dest, PrimVal::Bytes(0), dest_ty)
660     }
661 }