1 use std::time::{Duration, SystemTime};
3 use rustc::ty::layout::TyLayout;
5 use crate::stacked_borrows::Tag;
8 // Returns the time elapsed between now and the unix epoch as a `Duration` and the sign of the time
10 fn get_time<'tcx>() -> InterpResult<'tcx, Duration> {
12 .duration_since(SystemTime::UNIX_EPOCH)
13 .map_err(|_| err_unsup_format!("Time went backwards").into())
16 fn int_to_immty_checked<'tcx>(
18 layout: TyLayout<'tcx>,
19 ) -> InterpResult<'tcx, ImmTy<'tcx, Tag>> {
20 // If `int` does not fit in `size` bits, we error instead of letting
21 // `ImmTy::from_int` panic.
22 let size = layout.size;
23 let truncated = truncate(int as u128, size);
24 if sign_extend(truncated, size) as i128 != int {
26 "Signed value {:#x} does not fit in {} bits",
31 Ok(ImmTy::from_int(int, layout))
34 impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
35 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
36 // Foreign function used by linux
39 clk_id_op: OpTy<'tcx, Tag>,
40 tp_op: OpTy<'tcx, Tag>,
41 ) -> InterpResult<'tcx, i32> {
42 let this = self.eval_context_mut();
44 if !this.machine.communicate {
45 throw_unsup_format!("`clock_gettime` not available when isolation is enabled")
48 let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
49 if clk_id != this.eval_libc_i32("CLOCK_REALTIME")? {
50 let einval = this.eval_libc("EINVAL")?;
51 this.set_last_error(einval)?;
55 let tp = this.force_ptr(this.read_scalar(tp_op)?.not_undef()?)?;
57 let duration = get_time()?;
58 let tv_sec = duration.as_secs() as i128;
59 let tv_nsec = duration.subsec_nanos() as i128;
62 int_to_immty_checked(tv_sec, this.libc_ty_layout("time_t")?)?,
63 int_to_immty_checked(tv_nsec, this.libc_ty_layout("c_long")?)?,
66 this.write_immediates(&tp, &imms)?;
70 // Foreign function used by generic unix
73 tv_op: OpTy<'tcx, Tag>,
74 tz_op: OpTy<'tcx, Tag>,
75 ) -> InterpResult<'tcx, i32> {
76 let this = self.eval_context_mut();
78 if !this.machine.communicate {
79 throw_unsup_format!("`gettimeofday` not available when isolation is enabled")
81 // Using tz is obsolete and should always be null
82 let tz = this.read_scalar(tz_op)?.not_undef()?;
83 if !this.is_null(tz)? {
84 let einval = this.eval_libc("EINVAL")?;
85 this.set_last_error(einval)?;
89 let tv = this.force_ptr(this.read_scalar(tv_op)?.not_undef()?)?;
91 let duration = get_time()?;
92 let tv_sec = duration.as_secs() as i128;
93 let tv_usec = duration.subsec_micros() as i128;
96 int_to_immty_checked(tv_sec, this.libc_ty_layout("time_t")?)?,
97 int_to_immty_checked(tv_usec, this.libc_ty_layout("suseconds_t")?)?,
100 this.write_immediates(&tv, &imms)?;