Skip to content

WIP rustup #361

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ byteorder = { version = "1.1", features = ["i128"]}
cargo_metadata = { version = "0.2", optional = true }
regex = "0.2.2"
lazy_static = "1.0"
env_logger = "0.5.0-rc.1"
log = "0.4"

[features]
cargo_miri = ["cargo_metadata"]

[dev-dependencies]
compiletest_rs = { version = "0.3.3", features = ["tmp"] }
compiletest_rs = { version = "0.3.4", features = ["tmp"] }
21 changes: 12 additions & 9 deletions miri/bin/miri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,38 +191,41 @@ fn resource_limits_from_attributes(state: &CompileState) -> miri::ResourceLimits
}

fn init_logger() {
let format = |record: &log::LogRecord| {
if record.level() == log::LogLevel::Trace {
let format = |formatter: &mut env_logger::fmt::Formatter, record: &log::Record| {
use std::io::Write;
if record.level() == log::Level::Trace {
// prepend frame number
let indentation = log_settings::settings().indentation;
format!(
writeln!(
formatter,
"{indentation}:{lvl}:{module}: {text}",
lvl = record.level(),
module = record.location().module_path(),
module = record.module_path().unwrap_or("<unknown module>"),
indentation = indentation,
text = record.args(),
)
} else {
format!(
writeln!(
formatter,
"{lvl}:{module}: {text}",
lvl = record.level(),
module = record.location().module_path(),
module = record.module_path().unwrap_or("<unknown_module>"),
text = record.args(),
)
}
};

let mut builder = env_logger::LogBuilder::new();
let mut builder = env_logger::Builder::new();
builder.format(format).filter(
None,
log::LogLevelFilter::Info,
log::LevelFilter::Info,
);

if std::env::var("MIRI_LOG").is_ok() {
builder.parse(&std::env::var("MIRI_LOG").unwrap());
}

builder.init().unwrap();
builder.init();
}

fn find_sysroot() -> String {
Expand Down
31 changes: 20 additions & 11 deletions miri/fn_call.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use rustc::ty::{self, Ty};
use rustc::ty::layout::LayoutOf;
use rustc::ty::layout::{Align, LayoutOf};
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc::mir;
use syntax::attr;
Expand Down Expand Up @@ -111,7 +111,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
if size == 0 {
self.write_null(dest, dest_ty)?;
} else {
let align = self.memory.pointer_size();
let align = self.tcx.data_layout.pointer_align;
let ptr = self.memory.allocate(size, align, Some(MemoryKind::C.into()))?;
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
}
Expand Down Expand Up @@ -307,7 +307,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
// +1 for the null terminator
let value_copy = self.memory.allocate(
(value.len() + 1) as u64,
1,
Align::from_bytes(1, 1).unwrap(),
Some(MemoryKind::Env.into()),
)?;
self.memory.write_bytes(value_copy.into(), &value)?;
Expand Down Expand Up @@ -369,6 +369,8 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'

"sysconf" => {
let name = self.value_to_primval(args[0])?.to_u64()?;
let name_align = self.layout_of(args[0].ty)?.align;

trace!("sysconf() called with name {}", name);
// cache the sysconf integers via miri's global cache
let paths = &[
Expand All @@ -384,10 +386,11 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
};
// compute global if not cached
let val = match self.tcx.interpret_interner.borrow().get_cached(cid) {
Some(ptr) => ptr,
None => eval_body(self.tcx, instance, ty::ParamEnv::empty(traits::Reveal::All)).0?.0,
Some(ptr) => MemoryPointer::new(ptr, 0).into(),
None => eval_body(self.tcx, instance, ty::ParamEnv::empty(traits::Reveal::All))?.0,
};
let val = self.value_to_primval(ValTy { value: Value::ByRef(val), ty: args[0].ty })?.to_u64()?;
let val = self.value_to_primval(ValTy { value: Value::ByRef(val, name_align),
ty: args[0].ty })?.to_u64()?;
if val == name {
result = Some(path_value);
break;
Expand All @@ -406,6 +409,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
// Hook pthread calls that go to the thread-local storage memory subsystem
"pthread_key_create" => {
let key_ptr = self.into_ptr(args[0].value)?;
let key_align = self.layout_of(args[0].ty)?.align;

// Extract the function type out of the signature (that seems easier than constructing it ourselves...)
let dtor = match self.into_ptr(args[1].value)?.into_inner_primval() {
Expand All @@ -427,6 +431,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
}
self.memory.write_primval(
key_ptr.to_ptr()?,
key_align,
PrimVal::Bytes(key),
key_size.bytes(),
false,
Expand Down Expand Up @@ -559,7 +564,9 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
if !align.is_power_of_two() {
return err!(HeapAllocNonPowerOfTwoAlignment(align));
}
let ptr = self.memory.allocate(size, align, Some(MemoryKind::Rust.into()))?;
let ptr = self.memory.allocate(size,
Align::from_bytes(align, align).unwrap(),
Some(MemoryKind::Rust.into()))?;
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
}
"alloc::heap::::__rust_alloc_zeroed" => {
Expand All @@ -571,7 +578,9 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
if !align.is_power_of_two() {
return err!(HeapAllocNonPowerOfTwoAlignment(align));
}
let ptr = self.memory.allocate(size, align, Some(MemoryKind::Rust.into()))?;
let ptr = self.memory.allocate(size,
Align::from_bytes(align, align).unwrap(),
Some(MemoryKind::Rust.into()))?;
self.memory.write_repeat(ptr.into(), 0, size)?;
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
}
Expand All @@ -587,7 +596,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
}
self.memory.deallocate(
ptr,
Some((old_size, align)),
Some((old_size, Align::from_bytes(align, align).unwrap())),
MemoryKind::Rust.into(),
)?;
}
Expand All @@ -609,9 +618,9 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
let new_ptr = self.memory.reallocate(
ptr,
old_size,
old_align,
Align::from_bytes(old_align, old_align).unwrap(),
new_size,
new_align,
Align::from_bytes(new_align, new_align).unwrap(),
MemoryKind::Rust.into(),
)?;
self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?;
Expand Down
68 changes: 36 additions & 32 deletions miri/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rustc::traits::Reveal;
use rustc::ty::layout::{TyLayout, LayoutOf};
use rustc::ty;

use rustc::mir::interpret::{EvalResult, PrimVal, PrimValKind, Value, Pointer, AccessKind, PtrAndAlign};
use rustc::mir::interpret::{EvalResult, PrimVal, PrimValKind, Value, Pointer};
use rustc_mir::interpret::{Place, PlaceExtra, HasMemory, EvalContext, ValTy};

use helpers::EvalContextExt as HelperEvalContextExt;
Expand Down Expand Up @@ -87,8 +87,10 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
"atomic_load_acq" |
"volatile_load" => {
let ptr = self.into_ptr(args[0].value)?;
let align = self.layout_of(args[0].ty)?.align;

let valty = ValTy {
value: Value::by_ref(ptr),
value: Value::ByRef(ptr, align),
ty: substs.type_at(0),
};
self.write_value(valty, dest)?;
Expand All @@ -99,8 +101,9 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
"atomic_store_rel" |
"volatile_store" => {
let ty = substs.type_at(0);
let align = self.layout_of(ty)?.align;
let dest = self.into_ptr(args[0].value)?;
self.write_value_to_ptr(args[1].value, dest, ty)?;
self.write_value_to_ptr(args[1].value, dest, align, ty)?;
}

"atomic_fence_acq" => {
Expand All @@ -109,28 +112,30 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'

_ if intrinsic_name.starts_with("atomic_xchg") => {
let ty = substs.type_at(0);
let align = self.layout_of(ty)?.align;
let ptr = self.into_ptr(args[0].value)?;
let change = self.value_to_primval(args[1])?;
let old = self.read_value(ptr, ty)?;
let old = self.read_value(ptr, align, ty)?;
let old = match old {
Value::ByVal(val) => val,
Value::ByRef { .. } => bug!("just read the value, can't be byref"),
Value::ByValPair(..) => bug!("atomic_xchg doesn't work with nonprimitives"),
};
self.write_primval(dest, old, ty)?;
self.write_primval(
Place::from_primval_ptr(ptr),
Place::from_primval_ptr(ptr, align),
change,
ty,
)?;
}

_ if intrinsic_name.starts_with("atomic_cxchg") => {
let ty = substs.type_at(0);
let align = self.layout_of(ty)?.align;
let ptr = self.into_ptr(args[0].value)?;
let expect_old = self.value_to_primval(args[1])?;
let change = self.value_to_primval(args[2])?;
let old = self.read_value(ptr, ty)?;
let old = self.read_value(ptr, align, ty)?;
let old = match old {
Value::ByVal(val) => val,
Value::ByRef { .. } => bug!("just read the value, can't be byref"),
Expand All @@ -143,7 +148,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
};
self.write_value(valty, dest)?;
self.write_primval(
Place::from_primval_ptr(ptr),
Place::from_primval_ptr(ptr, dest_layout.align),
change,
ty,
)?;
Expand Down Expand Up @@ -175,9 +180,10 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
"atomic_xsub_acqrel" |
"atomic_xsub_relaxed" => {
let ty = substs.type_at(0);
let align = self.layout_of(ty)?.align;
let ptr = self.into_ptr(args[0].value)?;
let change = self.value_to_primval(args[1])?;
let old = self.read_value(ptr, ty)?;
let old = self.read_value(ptr, align, ty)?;
let old = match old {
Value::ByVal(val) => val,
Value::ByRef { .. } => bug!("just read the value, can't be byref"),
Expand All @@ -196,7 +202,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
};
// FIXME: what do atomics do on overflow?
let (val, _) = self.binary_op(op, old, ty, change, ty)?;
self.write_primval(Place::from_primval_ptr(ptr), val, ty)?;
self.write_primval(Place::from_primval_ptr(ptr, dest_layout.align), val, ty)?;
}

"breakpoint" => unimplemented!(), // halt miri
Expand All @@ -210,14 +216,16 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
if count * elem_size != 0 {
// TODO: We do not even validate alignment for the 0-bytes case. libstd relies on this in vec::IntoIter::next.
// Also see the write_bytes intrinsic.
let elem_align = elem_layout.align.abi();
let elem_align = elem_layout.align;
let src = self.into_ptr(args[0].value)?;
let src_align = self.layout_of(args[0].ty)?.align;
let dest = self.into_ptr(args[1].value)?;
self.memory.copy(
src,
src_align,
dest,
count * elem_size,
elem_align,
count * elem_size,
intrinsic_name.ends_with("_nonoverlapping"),
)?;
}
Expand All @@ -241,7 +249,8 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
"discriminant_value" => {
let ty = substs.type_at(0);
let adt_ptr = self.into_ptr(args[0].value)?;
let place = Place::from_primval_ptr(adt_ptr);
let adt_align = self.layout_of(args[0].ty)?.align;
let place = Place::from_primval_ptr(adt_ptr, adt_align);
let discr_val = self.read_discriminant_value(place, ty)?;
self.write_primval(dest, PrimVal::Bytes(discr_val), dest_layout.ty)?;
}
Expand Down Expand Up @@ -312,7 +321,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
let size = dest_layout.size.bytes();
let init = |this: &mut Self, val: Value| {
let zero_val = match val {
Value::ByRef(PtrAndAlign { ptr, .. }) => {
Value::ByRef(ptr, _) => {
// These writes have no alignment restriction anyway.
this.memory.write_repeat(ptr, 0, size)?;
val
Expand All @@ -326,7 +335,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
let ptr = this.alloc_ptr(dest_layout.ty)?;
let ptr = Pointer::from(PrimVal::Ptr(ptr));
this.memory.write_repeat(ptr, 0, size)?;
Value::by_ref(ptr)
Value::ByRef(ptr, dest_layout.align)
}
}
}
Expand All @@ -340,12 +349,11 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
match dest {
Place::Local { frame, local } => self.modify_local(frame, local, init)?,
Place::Ptr {
ptr: PtrAndAlign { ptr, aligned: true },
ptr: ptr,
align: _align,
extra: PlaceExtra::None,
} => self.memory.write_repeat(ptr, 0, size)?,
Place::Ptr { .. } => {
bug!("init intrinsic tried to write to fat or unaligned ptr target")
}
_ => bug!("TODO"),
}
}

Expand All @@ -367,7 +375,8 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
"move_val_init" => {
let ty = substs.type_at(0);
let ptr = self.into_ptr(args[0].value)?;
self.write_value_to_ptr(args[1].value, ptr, ty)?;
let align = self.layout_of(args[0].ty)?.align;
self.write_value_to_ptr(args[1].value, ptr, align, ty)?;
}

"needs_drop" => {
Expand Down Expand Up @@ -533,14 +542,10 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'

"transmute" => {
let src_ty = substs.type_at(0);
let src_align = self.layout_of(src_ty)?.align;
let ptr = self.force_allocation(dest)?.to_ptr()?;
self.write_maybe_aligned_mut(
/*aligned*/
false,
|ectx| {
ectx.write_value_to_ptr(args[0].value, ptr.into(), src_ty)
},
)?;
let dest_align = self.layout_of(substs.type_at(1))?.align;
self.write_value_to_ptr(args[0].value, ptr.into(), dest_align, src_ty);
}

"unchecked_shl" => {
Expand Down Expand Up @@ -612,7 +617,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
"uninit" => {
let size = dest_layout.size.bytes();
let uninit = |this: &mut Self, val: Value| match val {
Value::ByRef(PtrAndAlign { ptr, .. }) => {
Value::ByRef(ptr, _) => {
this.memory.mark_definedness(ptr, size, false)?;
Ok(val)
}
Expand All @@ -621,12 +626,11 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
match dest {
Place::Local { frame, local } => self.modify_local(frame, local, uninit)?,
Place::Ptr {
ptr: PtrAndAlign { ptr, aligned: true },
ptr: ptr,
align: _align,
extra: PlaceExtra::None,
} => self.memory.mark_definedness(ptr, size, false)?,
Place::Ptr { .. } => {
bug!("uninit intrinsic tried to write to fat or unaligned ptr target")
}
_ => bug!("todo"),
}
}

Expand All @@ -639,7 +643,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
if count > 0 {
// HashMap relies on write_bytes on a NULL ptr with count == 0 to work
// TODO: Should we, at least, validate the alignment? (Also see the copy intrinsic)
self.memory.check_align(ptr, ty_layout.align.abi(), Some(AccessKind::Write))?;
self.memory.check_align(ptr, ty_layout.align)?;
self.memory.write_repeat(ptr, val_byte, ty_layout.size.bytes() * count)?;
}
}
Expand Down
Loading