@@ -3,7 +3,6 @@ use rustc::ty::layout::{self, Align, LayoutOf, Size};
3
3
use rustc:: hir:: def_id:: { DefId , CRATE_DEF_INDEX } ;
4
4
use rustc:: mir;
5
5
use rustc_data_structures:: indexed_vec:: Idx ;
6
- use rustc_target:: spec:: abi:: Abi ;
7
6
use syntax:: attr;
8
7
use syntax:: codemap:: Span ;
9
8
@@ -60,7 +59,7 @@ fn write_discriminant_value<'a, 'mir, 'tcx: 'a + 'mir>(
60
59
}
61
60
62
61
pub trait EvalContextExt < ' tcx > {
63
- fn call_c_abi (
62
+ fn call_foreign_item (
64
63
& mut self ,
65
64
def_id : DefId ,
66
65
args : & [ ValTy < ' tcx > ] ,
@@ -105,9 +104,6 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
105
104
106
105
let def_id = instance. def_id ( ) ;
107
106
let item_path = self . tcx . absolute_item_path_str ( def_id) ;
108
- if item_path. starts_with ( "std::" ) {
109
- //println!("{}", item_path);
110
- }
111
107
match & * item_path {
112
108
"std::sys::unix::thread::guard::init" | "std::sys::unix::thread::guard::current" => {
113
109
// 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, '
178
174
Ok ( false )
179
175
}
180
176
181
- fn call_c_abi (
177
+ fn call_foreign_item (
182
178
& mut self ,
183
179
def_id : DefId ,
184
180
args : & [ ValTy < ' tcx > ] ,
@@ -215,6 +211,73 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
215
211
}
216
212
}
217
213
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
+
218
281
"syscall" => {
219
282
// TODO: read `syscall` ids like `sysconf` ids and
220
283
// 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, '
559
622
self . write_ptr ( dest, addr, dest_ty) ?;
560
623
}
561
624
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
562
634
_ => {
563
635
return err ! ( Unimplemented (
564
- format!( "can't call C ABI function: {}" , link_name) ,
636
+ format!( "can't call foreign function: {}" , link_name) ,
565
637
) ) ;
566
638
}
567
639
}
@@ -629,11 +701,11 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
629
701
|| EvalErrorKind :: NoMirFor ( path. clone ( ) ) ,
630
702
) ?;
631
703
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
634
706
// TODO: That functions actually has a similar preamble to what follows here. May make sense to
635
707
// unify these two mechanisms for "hooking into missing functions".
636
- self . call_c_abi (
708
+ self . call_foreign_item (
637
709
instance. def_id ( ) ,
638
710
args,
639
711
dest,
@@ -644,74 +716,6 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
644
716
}
645
717
646
718
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
-
715
719
// A Rust function is missing, which means we are running with MIR missing for libstd (or other dependencies).
716
720
// Still, we can make many things mostly work by "emulating" or ignoring some functions.
717
721
"std::io::_print" => {
@@ -733,12 +737,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
733
737
let bool = self . tcx . types . bool ;
734
738
self . write_scalar ( dest, Scalar :: from_bool ( false ) , bool) ?;
735
739
}
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
+
742
741
_ => return err ! ( NoMirFor ( path) ) ,
743
742
}
744
743
0 commit comments