From 2cbf4afa99a1a8953ed54abdcb292b45b79a8639 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Fri, 11 Oct 2019 00:55:32 -0500 Subject: [PATCH] Split `write_c_ints` into less specific helper functions --- src/helpers.rs | 39 +++++++++++++++------------------------ src/shims/time.rs | 40 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/helpers.rs b/src/helpers.rs index fea2307dcca5..892ba7b2401b 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -4,7 +4,7 @@ use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc::mir; use rustc::ty::{ self, - layout::{self, Align, LayoutOf, Size}, + layout::{self, Align, LayoutOf, Size, TyLayout}, }; use rand::RngCore; @@ -308,42 +308,26 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx self.eval_libc(name)?.to_i32() } - fn write_c_ints( + // Writes several `ImmTy`s contiguosly into memory. This is useful when you have to pack + // different values into an struct. + fn write_immediates( &mut self, ptr: &Pointer, - bits: &[i128], - ty_names: &[&str], + imms: &[ImmTy<'tcx, Tag>], ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let tcx = &{ this.tcx.tcx }; - let mut sizes = Vec::new(); - - for name in ty_names { - let ty = this.resolve_path(&["libc", name])?.ty(*tcx); - sizes.push(this.layout_of(ty)?.size); - } - let allocation = this.memory_mut().get_mut(ptr.alloc_id)?; let mut offset = Size::from_bytes(0); - for (&value, size) in bits.iter().zip(sizes) { - // If `value` does not fit in `size` bits, we error instead of letting - // `Scalar::from_int` panic. - let truncated = truncate(value as u128, size); - if sign_extend(truncated, size) as i128 != value { - throw_unsup_format!( - "Signed value {:#x} does not fit in {} bits", - value, - size.bits() - ) - } - + for imm in imms { + let size = imm.layout.size; allocation.write_scalar( tcx, ptr.offset(offset, tcx)?, - Scalar::from_int(value, size).into(), + imm.to_scalar()?.into(), size, )?; offset += size; @@ -351,4 +335,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx Ok(()) } + + fn libc_ty_layout(&mut self, name: &str) -> InterpResult<'tcx, TyLayout<'tcx>> { + let this = self.eval_context_mut(); + let tcx = &{ this.tcx.tcx }; + let ty = this.resolve_path(&["libc", name])?.ty(*tcx); + this.layout_of(ty) + } } diff --git a/src/shims/time.rs b/src/shims/time.rs index 2995bdc43464..3acc84dbc751 100644 --- a/src/shims/time.rs +++ b/src/shims/time.rs @@ -1,8 +1,12 @@ +use std::time::{Duration, SystemTime}; + +use rustc::ty::layout::TyLayout; + use crate::stacked_borrows::Tag; use crate::*; -use std::time::{Duration, SystemTime}; - +// Returns the time elapsed between now and the unix epoch as a `Duration` and the sign of the time +// interval fn get_time() -> (Duration, i128) { let mut sign = 1; let duration = SystemTime::now() @@ -14,6 +18,24 @@ fn get_time() -> (Duration, i128) { (duration, sign) } +fn int_to_immty_checked<'tcx>( + int: i128, + layout: TyLayout<'tcx>, +) -> InterpResult<'tcx, ImmTy<'tcx, Tag>> { + // If `int` does not fit in `size` bits, we error instead of letting + // `ImmTy::from_int` panic. + let size = layout.size; + let truncated = truncate(int as u128, size); + if sign_extend(truncated, size) as i128 != int { + throw_unsup_format!( + "Signed value {:#x} does not fit in {} bits", + int, + size.bits() + ) + } + Ok(ImmTy::from_int(int, layout)) +} + impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { // Foreign function used by linux @@ -45,7 +67,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx tv_nsec *= sign; } - this.write_c_ints(&tp, &[tv_sec, tv_nsec], &["time_t", "c_long"])?; + let imms = [ + int_to_immty_checked(tv_sec, this.libc_ty_layout("time_t")?)?, + int_to_immty_checked(tv_nsec, this.libc_ty_layout("c_long")?)?, + ]; + + this.write_immediates(&tp, &imms)?; Ok(0) } @@ -78,7 +105,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx tv_usec *= sign; } - this.write_c_ints(&tv, &[tv_sec, tv_usec], &["time_t", "suseconds_t"])?; + let imms = [ + int_to_immty_checked(tv_sec, this.libc_ty_layout("time_t")?)?, + int_to_immty_checked(tv_usec, this.libc_ty_layout("suseconds_t")?)?, + ]; + + this.write_immediates(&tv, &imms)?; Ok(0) }