Skip to content

Commit 05f2b2e

Browse files
committed
remove support for not having libstd MIR
1 parent b50662d commit 05f2b2e

File tree

2 files changed

+56
-156
lines changed

2 files changed

+56
-156
lines changed

src/fn_call.rs

+2-82
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,6 @@ pub trait EvalContextExt<'tcx, 'mir> {
1717
ret: mir::BasicBlock,
1818
) -> EvalResult<'tcx>;
1919

20-
/// Emulate a function that should have MIR but does not.
21-
/// This is solely to support execution without full MIR.
22-
/// Fail if emulating this function is not supported.
23-
/// This function will handle `goto_block` if needed.
24-
fn emulate_missing_fn(
25-
&mut self,
26-
path: String,
27-
args: &[OpTy<'tcx, Borrow>],
28-
dest: Option<PlaceTy<'tcx, Borrow>>,
29-
ret: Option<mir::BasicBlock>,
30-
) -> EvalResult<'tcx>;
31-
3220
fn find_fn(
3321
&mut self,
3422
instance: ty::Instance<'tcx>,
@@ -81,24 +69,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
8169
return Ok(None);
8270
}
8371

84-
// Otherwise we really want to see the MIR -- but if we do not have it, maybe we can
85-
// emulate something. This is a HACK to support running without a full-MIR libstd.
86-
let mir = match self.load_mir(instance.def) {
87-
Ok(mir) => mir,
88-
Err(EvalError { kind: EvalErrorKind::NoMirFor(path), .. }) => {
89-
self.emulate_missing_fn(
90-
path,
91-
args,
92-
dest,
93-
ret,
94-
)?;
95-
// `goto_block` already handled
96-
return Ok(None);
97-
}
98-
Err(other) => return Err(other),
99-
};
100-
101-
Ok(Some(mir))
72+
// Otherwise, load the MIR
73+
Ok(Some(self.load_mir(instance.def)?))
10274
}
10375

10476
fn emulate_foreign_item(
@@ -657,58 +629,6 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
657629
Ok(())
658630
}
659631

660-
fn emulate_missing_fn(
661-
&mut self,
662-
path: String,
663-
_args: &[OpTy<'tcx, Borrow>],
664-
dest: Option<PlaceTy<'tcx, Borrow>>,
665-
ret: Option<mir::BasicBlock>,
666-
) -> EvalResult<'tcx> {
667-
// In some cases in non-MIR libstd-mode, not having a destination is legit. Handle these early.
668-
match &path[..] {
669-
"std::panicking::rust_panic_with_hook" |
670-
"core::panicking::panic_fmt::::panic_impl" |
671-
"std::rt::begin_panic_fmt" =>
672-
return err!(MachineError("the evaluated program panicked".to_string())),
673-
_ => {}
674-
}
675-
676-
let dest = dest.ok_or_else(
677-
// Must be some function we do not support
678-
|| EvalErrorKind::NoMirFor(path.clone()),
679-
)?;
680-
681-
match &path[..] {
682-
// A Rust function is missing, which means we are running with MIR missing for libstd (or other dependencies).
683-
// Still, we can make many things mostly work by "emulating" or ignoring some functions.
684-
"std::io::_print" |
685-
"std::io::_eprint" => {
686-
warn!(
687-
"Ignoring output. To run programs that prints, make sure you have a libstd with full MIR."
688-
);
689-
}
690-
"std::thread::Builder::new" => {
691-
return err!(Unimplemented("miri does not support threading".to_owned()))
692-
}
693-
"std::env::args" => {
694-
return err!(Unimplemented(
695-
"miri does not support program arguments".to_owned(),
696-
))
697-
}
698-
"std::panicking::panicking" |
699-
"std::rt::panicking" => {
700-
// we abort on panic -> `std::rt::panicking` always returns false
701-
self.write_scalar(Scalar::from_bool(false), dest)?;
702-
}
703-
704-
_ => return err!(NoMirFor(path)),
705-
}
706-
707-
self.goto_block(ret)?;
708-
self.dump_place(*dest);
709-
Ok(())
710-
}
711-
712632
fn write_null(&mut self, dest: PlaceTy<'tcx, Borrow>) -> EvalResult<'tcx> {
713633
self.write_scalar(Scalar::from_int(0, dest.layout.size), dest)
714634
}

src/lib.rs

+54-74
Original file line numberDiff line numberDiff line change
@@ -80,82 +80,62 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
8080
));
8181
}
8282

83-
let libstd_has_mir = {
84-
let rustc_panic = ecx.resolve_path(&["std", "panicking", "rust_panic"])?;
85-
ecx.load_mir(rustc_panic.def).is_ok()
86-
};
87-
88-
if libstd_has_mir {
89-
let start_id = tcx.lang_items().start_fn().unwrap();
90-
let main_ret_ty = tcx.fn_sig(main_id).output();
91-
let main_ret_ty = main_ret_ty.no_bound_vars().unwrap();
92-
let start_instance = ty::Instance::resolve(
93-
ecx.tcx.tcx,
94-
ty::ParamEnv::reveal_all(),
95-
start_id,
96-
ecx.tcx.mk_substs(
97-
::std::iter::once(ty::subst::Kind::from(main_ret_ty)))
98-
).unwrap();
99-
let start_mir = ecx.load_mir(start_instance.def)?;
100-
101-
if start_mir.arg_count != 3 {
102-
return err!(AbiViolation(format!(
103-
"'start' lang item should have three arguments, but has {}",
104-
start_mir.arg_count
105-
)));
106-
}
107-
108-
// Return value (in static memory so that it does not count as leak)
109-
let ret = ecx.layout_of(start_mir.return_ty())?;
110-
let ret_ptr = ecx.allocate(ret, MiriMemoryKind::MutStatic.into())?;
111-
112-
// Push our stack frame
113-
ecx.push_stack_frame(
114-
start_instance,
115-
DUMMY_SP, // there is no call site, we want no span
116-
start_mir,
117-
Some(ret_ptr.into()),
118-
StackPopCleanup::None { cleanup: true },
119-
)?;
120-
121-
let mut args = ecx.frame().mir.args_iter();
122-
123-
// First argument: pointer to main()
124-
let main_ptr = ecx.memory_mut().create_fn_alloc(main_instance).with_default_tag();
125-
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
126-
ecx.write_scalar(Scalar::Ptr(main_ptr), dest)?;
127-
128-
// Second argument (argc): 1
129-
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
130-
ecx.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?;
131-
132-
// FIXME: extract main source file path
133-
// Third argument (argv): &[b"foo"]
134-
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
135-
let foo = ecx.memory_mut().allocate_static_bytes(b"foo\0").with_default_tag();
136-
let foo_ty = ecx.tcx.mk_imm_ptr(ecx.tcx.types.u8);
137-
let foo_layout = ecx.layout_of(foo_ty)?;
138-
let foo_place = ecx.allocate(foo_layout, MiriMemoryKind::Env.into())?;
139-
ecx.write_scalar(Scalar::Ptr(foo), foo_place.into())?;
140-
ecx.memory_mut().mark_immutable(foo_place.to_ptr()?.alloc_id)?;
141-
ecx.write_scalar(foo_place.ptr, dest)?;
142-
143-
assert!(args.next().is_none(), "start lang item has more arguments than expected");
144-
} else {
145-
let ret_place = MPlaceTy::dangling(ecx.layout_of(tcx.mk_unit())?, &ecx).into();
146-
ecx.push_stack_frame(
147-
main_instance,
148-
DUMMY_SP, // there is no call site, we want no span
149-
main_mir,
150-
Some(ret_place),
151-
StackPopCleanup::None { cleanup: true },
152-
)?;
153-
154-
// No arguments
155-
let mut args = ecx.frame().mir.args_iter();
156-
assert!(args.next().is_none(), "main function must not have arguments");
83+
let start_id = tcx.lang_items().start_fn().unwrap();
84+
let main_ret_ty = tcx.fn_sig(main_id).output();
85+
let main_ret_ty = main_ret_ty.no_bound_vars().unwrap();
86+
let start_instance = ty::Instance::resolve(
87+
ecx.tcx.tcx,
88+
ty::ParamEnv::reveal_all(),
89+
start_id,
90+
ecx.tcx.mk_substs(
91+
::std::iter::once(ty::subst::Kind::from(main_ret_ty)))
92+
).unwrap();
93+
let start_mir = ecx.load_mir(start_instance.def)?;
94+
95+
if start_mir.arg_count != 3 {
96+
return err!(AbiViolation(format!(
97+
"'start' lang item should have three arguments, but has {}",
98+
start_mir.arg_count
99+
)));
157100
}
158101

102+
// Return value (in static memory so that it does not count as leak)
103+
let ret = ecx.layout_of(start_mir.return_ty())?;
104+
let ret_ptr = ecx.allocate(ret, MiriMemoryKind::MutStatic.into())?;
105+
106+
// Push our stack frame
107+
ecx.push_stack_frame(
108+
start_instance,
109+
DUMMY_SP, // there is no call site, we want no span
110+
start_mir,
111+
Some(ret_ptr.into()),
112+
StackPopCleanup::None { cleanup: true },
113+
)?;
114+
115+
let mut args = ecx.frame().mir.args_iter();
116+
117+
// First argument: pointer to main()
118+
let main_ptr = ecx.memory_mut().create_fn_alloc(main_instance).with_default_tag();
119+
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
120+
ecx.write_scalar(Scalar::Ptr(main_ptr), dest)?;
121+
122+
// Second argument (argc): 1
123+
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
124+
ecx.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?;
125+
126+
// FIXME: extract main source file path
127+
// Third argument (argv): &[b"foo"]
128+
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
129+
let foo = ecx.memory_mut().allocate_static_bytes(b"foo\0").with_default_tag();
130+
let foo_ty = ecx.tcx.mk_imm_ptr(ecx.tcx.types.u8);
131+
let foo_layout = ecx.layout_of(foo_ty)?;
132+
let foo_place = ecx.allocate(foo_layout, MiriMemoryKind::Env.into())?;
133+
ecx.write_scalar(Scalar::Ptr(foo), foo_place.into())?;
134+
ecx.memory_mut().mark_immutable(foo_place.to_ptr()?.alloc_id)?;
135+
ecx.write_scalar(foo_place.ptr, dest)?;
136+
137+
assert!(args.next().is_none(), "start lang item has more arguments than expected");
138+
159139
Ok(ecx)
160140
}
161141

0 commit comments

Comments
 (0)