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!("Times before the Unix epoch are not supported").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 this.check_no_isolation("clock_gettime")?;
46 let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
47 if clk_id != this.eval_libc_i32("CLOCK_REALTIME")? {
48 let einval = this.eval_libc("EINVAL")?;
49 this.set_last_error(einval)?;
53 let tp = this.deref_operand(tp_op)?;
55 let duration = get_time()?;
56 let tv_sec = duration.as_secs() as i128;
57 let tv_nsec = duration.subsec_nanos() as i128;
60 int_to_immty_checked(tv_sec, this.libc_ty_layout("time_t")?)?,
61 int_to_immty_checked(tv_nsec, this.libc_ty_layout("c_long")?)?,
64 this.write_packed_immediates(&tp, &imms)?;
68 // Foreign function used by generic unix (in particular macOS)
71 tv_op: OpTy<'tcx, Tag>,
72 tz_op: OpTy<'tcx, Tag>,
73 ) -> InterpResult<'tcx, i32> {
74 let this = self.eval_context_mut();
76 this.check_no_isolation("gettimeofday")?;
77 // Using tz is obsolete and should always be null
78 let tz = this.read_scalar(tz_op)?.not_undef()?;
79 if !this.is_null(tz)? {
80 let einval = this.eval_libc("EINVAL")?;
81 this.set_last_error(einval)?;
85 let tv = this.deref_operand(tv_op)?;
87 let duration = get_time()?;
88 let tv_sec = duration.as_secs() as i128;
89 let tv_usec = duration.subsec_micros() as i128;
92 int_to_immty_checked(tv_sec, this.libc_ty_layout("time_t")?)?,
93 int_to_immty_checked(tv_usec, this.libc_ty_layout("suseconds_t")?)?,
96 this.write_packed_immediates(&tv, &imms)?;