1
- use rustc:: hir:: def_id:: DefId ;
1
+ use rustc:: hir:: def_id:: { DefId , CRATE_DEF_INDEX } ;
2
2
use rustc:: mir;
3
3
use rustc:: ty:: { self , TypeVariants , Ty } ;
4
4
use rustc:: ty:: layout:: Layout ;
@@ -13,6 +13,8 @@ use memory::{MemoryPointer, TlsKey};
13
13
use value:: { PrimVal , Value } ;
14
14
use rustc_data_structures:: indexed_vec:: Idx ;
15
15
16
+ use std:: mem;
17
+
16
18
mod drop;
17
19
mod intrinsic;
18
20
@@ -853,12 +855,32 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
853
855
"sysconf" => {
854
856
let name = self . value_to_primval ( args[ 0 ] , usize) ?. to_u64 ( ) ?;
855
857
trace ! ( "sysconf() called with name {}" , name) ;
856
- let result = match name {
857
- 30 => PrimVal :: Bytes ( 4096 ) , // _SC_PAGESIZE
858
- 70 => PrimVal :: from_i128 ( -1 ) , // _SC_GETPW_R_SIZE_MAX
859
- _ => return Err ( EvalError :: Unimplemented ( format ! ( "Unimplemented sysconf name: {}" , name) ) )
860
- } ;
861
- self . write_primval ( dest, result, dest_ty) ?;
858
+ // cache the sysconf integers via miri's global cache
859
+ let paths = & [
860
+ ( & [ "libc" , "_SC_PAGESIZE" ] , PrimVal :: Bytes ( 4096 ) ) ,
861
+ ( & [ "libc" , "_SC_GETPW_R_SIZE_MAX" ] , PrimVal :: from_i128 ( -1 ) ) ,
862
+ ] ;
863
+ let mut result = None ;
864
+ for & ( path, path_value) in paths {
865
+ if let Ok ( instance) = self . resolve_path ( path) {
866
+ use lvalue:: GlobalId ;
867
+ let cid = GlobalId { instance, promoted : None } ;
868
+ // compute global if not cached
869
+ let val = match self . globals . get ( & cid) . map ( |glob| glob. value ) {
870
+ Some ( value) => self . value_to_primval ( value, usize) ?. to_u64 ( ) ?,
871
+ None => :: const_eval:: eval_body_as_primval ( self . tcx , instance) ?. 0 . to_u64 ( ) ?,
872
+ } ;
873
+ if val == name {
874
+ result = Some ( path_value) ;
875
+ break ;
876
+ }
877
+ }
878
+ }
879
+ if let Some ( result) = result {
880
+ self . write_primval ( dest, result, dest_ty) ?;
881
+ } else {
882
+ return Err ( EvalError :: Unimplemented ( format ! ( "Unimplemented sysconf name: {}" , name) ) ) ;
883
+ }
862
884
}
863
885
864
886
// Hook pthread calls that go to the thread-local storage memory subsystem
@@ -933,4 +955,41 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
933
955
self . goto_block ( dest_block) ;
934
956
Ok ( ( ) )
935
957
}
958
+
959
+ /// Get an instance for a path.
960
+ fn resolve_path ( & self , path : & [ & str ] ) -> EvalResult < ' tcx , ty:: Instance < ' tcx > > {
961
+ let cstore = & self . tcx . sess . cstore ;
962
+
963
+ let crates = cstore. crates ( ) ;
964
+ crates. iter ( )
965
+ . find ( |& & krate| cstore. crate_name ( krate) == path[ 0 ] )
966
+ . and_then ( |krate| {
967
+ let krate = DefId {
968
+ krate : * krate,
969
+ index : CRATE_DEF_INDEX ,
970
+ } ;
971
+ let mut items = cstore. item_children ( krate, self . tcx . sess ) ;
972
+ let mut path_it = path. iter ( ) . skip ( 1 ) . peekable ( ) ;
973
+
974
+ while let Some ( segment) = path_it. next ( ) {
975
+ for item in & mem:: replace ( & mut items, vec ! [ ] ) {
976
+ if item. ident . name == * segment {
977
+ if path_it. peek ( ) . is_none ( ) {
978
+ return Some ( ty:: Instance :: mono ( self . tcx , item. def . def_id ( ) ) ) ;
979
+ }
980
+
981
+ items = cstore. item_children ( item. def . def_id ( ) , self . tcx . sess ) ;
982
+ break ;
983
+ }
984
+ }
985
+ }
986
+ None
987
+ } )
988
+ . ok_or_else ( || {
989
+ let path = path. iter ( )
990
+ . map ( |& s| s. to_owned ( ) )
991
+ . collect ( ) ;
992
+ EvalError :: PathNotFound ( path)
993
+ } )
994
+ }
936
995
}
0 commit comments