Skip to content

adjust for goto_block refactoring #1077

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

Merged
merged 3 commits into from
Nov 27, 2019
Merged
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
2 changes: 1 addition & 1 deletion rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bd816fd76f4f7a040ca7ac8ca5bc556d761f96fa
809e180a76ce97340bf4354ff357bc59e3ca40b2
14 changes: 8 additions & 6 deletions src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,16 +201,18 @@ pub fn eval_main<'tcx>(tcx: TyCtxt<'tcx>, main_id: DefId, config: MiriConfig) ->
// Process the result.
match res {
Ok(return_code) => {
let leaks = ecx.memory.leak_report();
// Disable the leak test on some platforms where we do not
// correctly implement TLS destructors.
let target_os = ecx.tcx.tcx.sess.target.target.target_os.to_lowercase();
let ignore_leaks = target_os == "windows" || target_os == "macos";
if !ignore_leaks && leaks != 0 {
tcx.sess.err("the evaluated program leaked memory");
// Ignore the provided return code - let the reported error
// determine the return code.
return None;
if !ignore_leaks {
let leaks = ecx.memory.leak_report();
if leaks != 0 {
tcx.sess.err("the evaluated program leaked memory");
// Ignore the provided return code - let the reported error
// determine the return code.
return None;
}
}
return Some(return_code)
}
Expand Down
16 changes: 7 additions & 9 deletions src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,22 +186,21 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
ecx: &mut InterpCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Tag>],
dest: Option<PlaceTy<'tcx, Tag>>,
ret: Option<mir::BasicBlock>,
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
unwind: Option<mir::BasicBlock>,
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
ecx.find_fn(instance, args, dest, ret, unwind)
ecx.find_fn(instance, args, ret, unwind)
}

#[inline(always)]
fn call_extra_fn(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
fn_val: Dlsym,
args: &[OpTy<'tcx, Tag>],
dest: Option<PlaceTy<'tcx, Tag>>,
ret: Option<mir::BasicBlock>,
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
_unwind: Option<mir::BasicBlock>,
) -> InterpResult<'tcx> {
ecx.call_dlsym(fn_val, args, dest, ret)
ecx.call_dlsym(fn_val, args, ret)
}

#[inline(always)]
Expand All @@ -210,11 +209,10 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
span: Span,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Tag>],
dest: Option<PlaceTy<'tcx, Tag>>,
ret: Option<mir::BasicBlock>,
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
unwind: Option<mir::BasicBlock>,
) -> InterpResult<'tcx> {
ecx.call_intrinsic(span, instance, args, dest, ret, unwind)
ecx.call_intrinsic(span, instance, args, ret, unwind)
}

#[inline(always)]
Expand Down
9 changes: 3 additions & 6 deletions src/shims/dlsym.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
&mut self,
dlsym: Dlsym,
args: &[OpTy<'tcx, Tag>],
dest: Option<PlaceTy<'tcx, Tag>>,
ret: Option<mir::BasicBlock>,
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
) -> InterpResult<'tcx> {
use self::Dlsym::*;

let this = self.eval_context_mut();

let dest = dest.expect("we don't support any diverging dlsym");
let ret = ret.expect("dest is `Some` but ret is `None`");
let (dest, ret) = ret.expect("we don't support any diverging dlsym");

match dlsym {
GetEntropy => {
Expand All @@ -46,8 +43,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
}
}

this.goto_block(Some(ret))?;
this.dump_place(*dest);
this.go_to_block(ret);
Ok(())
}
}
17 changes: 8 additions & 9 deletions src/shims/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
&mut self,
def_id: DefId,
args: &[OpTy<'tcx, Tag>],
dest: Option<PlaceTy<'tcx, Tag>>,
ret: Option<mir::BasicBlock>,
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
_unwind: Option<mir::BasicBlock>
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
let this = self.eval_context_mut();
Expand All @@ -129,7 +128,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let tcx = &{ this.tcx.tcx };

// First: functions that diverge.
match link_name {
let (dest, ret) = match link_name {
// Note that this matches calls to the *foreign* item `__rust_start_panic* -
// that is, calls to `extern "Rust" { fn __rust_start_panic(...) }`.
// We forward this to the underlying *implementation* in the panic runtime crate.
Expand All @@ -154,15 +153,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
return Err(InterpError::Exit(code).into());
}
_ => {
if dest.is_none() {
if let Some(p) = ret {
p
} else {
throw_unsup_format!("can't call (diverging) foreign function: {}", link_name);
}
}
}
};

// Next: functions that assume a ret and dest.
let dest = dest.expect("we already checked for a dest");
let ret = ret.expect("dest is `Some` but ret is `None`");
// Next: functions that return.
match link_name {
"malloc" => {
let size = this.read_scalar(args[0])?.to_machine_usize(this)?;
Expand Down Expand Up @@ -928,8 +927,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
_ => throw_unsup_format!("can't call foreign function: {}", link_name),
}

this.goto_block(Some(ret))?;
this.dump_place(*dest);
this.go_to_block(ret);
Ok(None)
}

Expand Down
27 changes: 13 additions & 14 deletions src/shims/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
span: Span,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Tag>],
dest: Option<PlaceTy<'tcx, Tag>>,
_ret: Option<mir::BasicBlock>,
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
unwind: Option<mir::BasicBlock>
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
if this.emulate_intrinsic(span, instance, args, dest)? {
if this.emulate_intrinsic(span, instance, args, ret)? {
return Ok(());
}
let tcx = &{this.tcx.tcx};
Expand All @@ -32,23 +31,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// that might still hang around!
let intrinsic_name = &*tcx.item_name(instance.def_id()).as_str();

// Handle diverging intrinsics
match intrinsic_name {
// Handle diverging intrinsics.
let (dest, ret) = match intrinsic_name {
"abort" => {
// FIXME: Add a better way of indicating 'abnormal' termination,
// since this is not really an 'unsupported' behavior
throw_unsup_format!("the evaluated program aborted!");
}
"miri_start_panic" => return this.handle_miri_start_panic(args, unwind),
_ => {}
}

// Handle non-diverging intrinsics
// The intrinsic itself cannot diverge (otherwise, we would have handled it above),
// so if we got here without a return place that's UB (can happen e.g., for transmute returning `!`).
let dest = match dest {
Some(dest) => dest,
None => throw_ub!(Unreachable)
_ => {
if let Some(p) = ret {
p
} else {
throw_unsup_format!("unimplemented (diverging) intrinsic: {}", intrinsic_name);
}
}
};

match intrinsic_name {
Expand Down Expand Up @@ -581,6 +578,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
name => throw_unsup_format!("unimplemented intrinsic: {}", name),
}

this.dump_place(*dest);
this.go_to_block(ret);
Ok(())
}
}
11 changes: 5 additions & 6 deletions src/shims/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
&mut self,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Tag>],
dest: Option<PlaceTy<'tcx, Tag>>,
ret: Option<mir::BasicBlock>,
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
unwind: Option<mir::BasicBlock>
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
let this = self.eval_context_mut();
trace!(
"eval_fn_call: {:#?}, {:?}",
instance,
dest.map(|place| *place)
ret.map(|p| *p.0)
);

// There are some more lang items we want to hook that CTFE does not hook (yet).
if this.tcx.lang_items().align_offset_fn() == Some(instance.def.def_id()) {
let dest = dest.unwrap();
let (dest, ret) = ret.unwrap();
let n = this
.align_offset(args[0], args[1])?
.unwrap_or_else(|| this.truncate(u128::max_value(), dest.layout));
this.write_scalar(Scalar::from_uint(n, dest.layout.size), dest)?;
this.goto_block(ret)?;
this.go_to_block(ret);
return Ok(None);
}

Expand All @@ -46,7 +45,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// to run extra MIR), and Ok(Some(body)) if we found MIR to run for the
// foreign function
// Any needed call to `goto_block` will be performed by `emulate_foreign_item`.
return this.emulate_foreign_item(instance.def_id(), args, dest, ret, unwind);
return this.emulate_foreign_item(instance.def_id(), args, ret, unwind);
}

// Otherwise, load the MIR.
Expand Down
5 changes: 1 addition & 4 deletions src/shims/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.machine.panic_payload = Some(scalar);

// Jump to the unwind block to begin unwinding.
// We don't use `goto_block` as that is just meant for normal returns.
let next_frame = this.frame_mut();
next_frame.block = unwind;
next_frame.stmt = 0;
this.unwind_to_block(unwind);
return Ok(())
}

Expand Down