Skip to content

Commit fd6dad7

Browse files
authored
Merge pull request #406 from RalfJung/windows
handle all foreign items like we handle C ABI shims
2 parents fe4f62a + 60d18db commit fd6dad7

File tree

1 file changed

+83
-84
lines changed

1 file changed

+83
-84
lines changed

src/fn_call.rs

Lines changed: 83 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use rustc::ty::layout::{self, Align, LayoutOf, Size};
33
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
44
use rustc::mir;
55
use rustc_data_structures::indexed_vec::Idx;
6-
use rustc_target::spec::abi::Abi;
76
use syntax::attr;
87
use syntax::codemap::Span;
98

@@ -60,7 +59,7 @@ fn write_discriminant_value<'a, 'mir, 'tcx: 'a + 'mir>(
6059
}
6160

6261
pub trait EvalContextExt<'tcx> {
63-
fn call_c_abi(
62+
fn call_foreign_item(
6463
&mut self,
6564
def_id: DefId,
6665
args: &[ValTy<'tcx>],
@@ -105,9 +104,6 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
105104

106105
let def_id = instance.def_id();
107106
let item_path = self.tcx.absolute_item_path_str(def_id);
108-
if item_path.starts_with("std::") {
109-
//println!("{}", item_path);
110-
}
111107
match &*item_path {
112108
"std::sys::unix::thread::guard::init" | "std::sys::unix::thread::guard::current" => {
113109
// Return None, as it doesn't make sense to return Some, because miri detects stack overflow itself.
@@ -178,7 +174,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
178174
Ok(false)
179175
}
180176

181-
fn call_c_abi(
177+
fn call_foreign_item(
182178
&mut self,
183179
def_id: DefId,
184180
args: &[ValTy<'tcx>],
@@ -215,6 +211,73 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
215211
}
216212
}
217213

214+
"__rust_alloc" => {
215+
let size = self.value_to_scalar(args[0])?.to_usize(self)?;
216+
let align = self.value_to_scalar(args[1])?.to_usize(self)?;
217+
if size == 0 {
218+
return err!(HeapAllocZeroBytes);
219+
}
220+
if !align.is_power_of_two() {
221+
return err!(HeapAllocNonPowerOfTwoAlignment(align));
222+
}
223+
let ptr = self.memory.allocate(Size::from_bytes(size),
224+
Align::from_bytes(align, align).unwrap(),
225+
MemoryKind::Rust.into())?;
226+
self.write_scalar(dest, Scalar::Ptr(ptr), dest_ty)?;
227+
}
228+
"__rust_alloc_zeroed" => {
229+
let size = self.value_to_scalar(args[0])?.to_usize(self)?;
230+
let align = self.value_to_scalar(args[1])?.to_usize(self)?;
231+
if size == 0 {
232+
return err!(HeapAllocZeroBytes);
233+
}
234+
if !align.is_power_of_two() {
235+
return err!(HeapAllocNonPowerOfTwoAlignment(align));
236+
}
237+
let ptr = self.memory.allocate(Size::from_bytes(size),
238+
Align::from_bytes(align, align).unwrap(),
239+
MemoryKind::Rust.into())?;
240+
self.memory.write_repeat(ptr.into(), 0, Size::from_bytes(size))?;
241+
self.write_scalar(dest, Scalar::Ptr(ptr), dest_ty)?;
242+
}
243+
"__rust_dealloc" => {
244+
let ptr = self.into_ptr(args[0].value)?.to_ptr()?;
245+
let old_size = self.value_to_scalar(args[1])?.to_usize(self)?;
246+
let align = self.value_to_scalar(args[2])?.to_usize(self)?;
247+
if old_size == 0 {
248+
return err!(HeapAllocZeroBytes);
249+
}
250+
if !align.is_power_of_two() {
251+
return err!(HeapAllocNonPowerOfTwoAlignment(align));
252+
}
253+
self.memory.deallocate(
254+
ptr,
255+
Some((Size::from_bytes(old_size), Align::from_bytes(align, align).unwrap())),
256+
MemoryKind::Rust.into(),
257+
)?;
258+
}
259+
"__rust_realloc" => {
260+
let ptr = self.into_ptr(args[0].value)?.to_ptr()?;
261+
let old_size = self.value_to_scalar(args[1])?.to_usize(self)?;
262+
let align = self.value_to_scalar(args[2])?.to_usize(self)?;
263+
let new_size = self.value_to_scalar(args[3])?.to_usize(self)?;
264+
if old_size == 0 || new_size == 0 {
265+
return err!(HeapAllocZeroBytes);
266+
}
267+
if !align.is_power_of_two() {
268+
return err!(HeapAllocNonPowerOfTwoAlignment(align));
269+
}
270+
let new_ptr = self.memory.reallocate(
271+
ptr,
272+
Size::from_bytes(old_size),
273+
Align::from_bytes(align, align).unwrap(),
274+
Size::from_bytes(new_size),
275+
Align::from_bytes(align, align).unwrap(),
276+
MemoryKind::Rust.into(),
277+
)?;
278+
self.write_scalar(dest, Scalar::Ptr(new_ptr), dest_ty)?;
279+
}
280+
218281
"syscall" => {
219282
// TODO: read `syscall` ids like `sysconf` ids and
220283
// figure out some way to actually process some of them
@@ -559,9 +622,18 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
559622
self.write_ptr(dest, addr, dest_ty)?;
560623
}
561624

625+
// Windows API subs
626+
"AddVectoredExceptionHandler" |
627+
"SetThreadStackGuarantee" => {
628+
let usize = self.tcx.types.usize;
629+
// any non zero value works for the stdlib. This is just used for stackoverflows anyway
630+
self.write_scalar(dest, Scalar::from_u128(1), usize)?;
631+
},
632+
633+
// We can't execute anything else
562634
_ => {
563635
return err!(Unimplemented(
564-
format!("can't call C ABI function: {}", link_name),
636+
format!("can't call foreign function: {}", link_name),
565637
));
566638
}
567639
}
@@ -629,11 +701,11 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
629701
|| EvalErrorKind::NoMirFor(path.clone()),
630702
)?;
631703

632-
if sig.abi == Abi::C {
633-
// An external C function
704+
if self.tcx.is_foreign_item(instance.def_id()) {
705+
// An external function
634706
// TODO: That functions actually has a similar preamble to what follows here. May make sense to
635707
// unify these two mechanisms for "hooking into missing functions".
636-
self.call_c_abi(
708+
self.call_foreign_item(
637709
instance.def_id(),
638710
args,
639711
dest,
@@ -644,74 +716,6 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
644716
}
645717

646718
match &path[..] {
647-
// Allocators are magic. They have no MIR, even when the rest of libstd does.
648-
"alloc::alloc::::__rust_alloc" => {
649-
let size = self.value_to_scalar(args[0])?.to_usize(self)?;
650-
let align = self.value_to_scalar(args[1])?.to_usize(self)?;
651-
if size == 0 {
652-
return err!(HeapAllocZeroBytes);
653-
}
654-
if !align.is_power_of_two() {
655-
return err!(HeapAllocNonPowerOfTwoAlignment(align));
656-
}
657-
let ptr = self.memory.allocate(Size::from_bytes(size),
658-
Align::from_bytes(align, align).unwrap(),
659-
MemoryKind::Rust.into())?;
660-
self.write_scalar(dest, Scalar::Ptr(ptr), dest_ty)?;
661-
}
662-
"alloc::alloc::::__rust_alloc_zeroed" => {
663-
let size = self.value_to_scalar(args[0])?.to_usize(self)?;
664-
let align = self.value_to_scalar(args[1])?.to_usize(self)?;
665-
if size == 0 {
666-
return err!(HeapAllocZeroBytes);
667-
}
668-
if !align.is_power_of_two() {
669-
return err!(HeapAllocNonPowerOfTwoAlignment(align));
670-
}
671-
let ptr = self.memory.allocate(Size::from_bytes(size),
672-
Align::from_bytes(align, align).unwrap(),
673-
MemoryKind::Rust.into())?;
674-
self.memory.write_repeat(ptr.into(), 0, Size::from_bytes(size))?;
675-
self.write_scalar(dest, Scalar::Ptr(ptr), dest_ty)?;
676-
}
677-
"alloc::alloc::::__rust_dealloc" => {
678-
let ptr = self.into_ptr(args[0].value)?.to_ptr()?;
679-
let old_size = self.value_to_scalar(args[1])?.to_usize(self)?;
680-
let align = self.value_to_scalar(args[2])?.to_usize(self)?;
681-
if old_size == 0 {
682-
return err!(HeapAllocZeroBytes);
683-
}
684-
if !align.is_power_of_two() {
685-
return err!(HeapAllocNonPowerOfTwoAlignment(align));
686-
}
687-
self.memory.deallocate(
688-
ptr,
689-
Some((Size::from_bytes(old_size), Align::from_bytes(align, align).unwrap())),
690-
MemoryKind::Rust.into(),
691-
)?;
692-
}
693-
"alloc::alloc::::__rust_realloc" => {
694-
let ptr = self.into_ptr(args[0].value)?.to_ptr()?;
695-
let old_size = self.value_to_scalar(args[1])?.to_usize(self)?;
696-
let align = self.value_to_scalar(args[2])?.to_usize(self)?;
697-
let new_size = self.value_to_scalar(args[3])?.to_usize(self)?;
698-
if old_size == 0 || new_size == 0 {
699-
return err!(HeapAllocZeroBytes);
700-
}
701-
if !align.is_power_of_two() {
702-
return err!(HeapAllocNonPowerOfTwoAlignment(align));
703-
}
704-
let new_ptr = self.memory.reallocate(
705-
ptr,
706-
Size::from_bytes(old_size),
707-
Align::from_bytes(align, align).unwrap(),
708-
Size::from_bytes(new_size),
709-
Align::from_bytes(align, align).unwrap(),
710-
MemoryKind::Rust.into(),
711-
)?;
712-
self.write_scalar(dest, Scalar::Ptr(new_ptr), dest_ty)?;
713-
}
714-
715719
// A Rust function is missing, which means we are running with MIR missing for libstd (or other dependencies).
716720
// Still, we can make many things mostly work by "emulating" or ignoring some functions.
717721
"std::io::_print" => {
@@ -733,12 +737,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
733737
let bool = self.tcx.types.bool;
734738
self.write_scalar(dest, Scalar::from_bool(false), bool)?;
735739
}
736-
"std::sys::imp::c::::AddVectoredExceptionHandler" |
737-
"std::sys::imp::c::::SetThreadStackGuarantee" => {
738-
let usize = self.tcx.types.usize;
739-
// any non zero value works for the stdlib. This is just used for stackoverflows anyway
740-
self.write_scalar(dest, Scalar::from_u128(1), usize)?;
741-
},
740+
742741
_ => return err!(NoMirFor(path)),
743742
}
744743

0 commit comments

Comments
 (0)