@@ -57,8 +57,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
57
57
58
58
/// Evaluates the scalar at the specified path. Returns Some(val)
59
59
/// if the path could be resolved, and None otherwise
60
- fn eval_path_scalar ( & mut self , path : & [ & str ] ) -> InterpResult < ' tcx , Scalar < Tag > > {
61
- let this = self . eval_context_mut ( ) ;
60
+ fn eval_path_scalar ( & self , path : & [ & str ] ) -> InterpResult < ' tcx , Scalar < Tag > > {
61
+ let this = self . eval_context_ref ( ) ;
62
62
let instance = this. resolve_path ( path) ;
63
63
let cid = GlobalId { instance, promoted : None } ;
64
64
let const_val = this. eval_to_allocation ( cid) ?;
@@ -67,46 +67,103 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
67
67
}
68
68
69
69
/// Helper function to get a `libc` constant as a `Scalar`.
70
- fn eval_libc ( & mut self , name : & str ) -> InterpResult < ' tcx , Scalar < Tag > > {
71
- self . eval_context_mut ( ) . eval_path_scalar ( & [ "libc" , name] )
70
+ fn eval_libc ( & self , name : & str ) -> InterpResult < ' tcx , Scalar < Tag > > {
71
+ self . eval_path_scalar ( & [ "libc" , name] )
72
72
}
73
73
74
74
/// Helper function to get a `libc` constant as an `i32`.
75
- fn eval_libc_i32 ( & mut self , name : & str ) -> InterpResult < ' tcx , i32 > {
75
+ fn eval_libc_i32 ( & self , name : & str ) -> InterpResult < ' tcx , i32 > {
76
76
// TODO: Cache the result.
77
77
self . eval_libc ( name) ?. to_i32 ( )
78
78
}
79
79
80
80
/// Helper function to get a `windows` constant as a `Scalar`.
81
- fn eval_windows ( & mut self , module : & str , name : & str ) -> InterpResult < ' tcx , Scalar < Tag > > {
82
- self . eval_context_mut ( ) . eval_path_scalar ( & [ "std" , "sys" , "windows" , module, name] )
81
+ fn eval_windows ( & self , module : & str , name : & str ) -> InterpResult < ' tcx , Scalar < Tag > > {
82
+ self . eval_context_ref ( ) . eval_path_scalar ( & [ "std" , "sys" , "windows" , module, name] )
83
83
}
84
84
85
85
/// Helper function to get a `windows` constant as a `u64`.
86
- fn eval_windows_u64 ( & mut self , module : & str , name : & str ) -> InterpResult < ' tcx , u64 > {
86
+ fn eval_windows_u64 ( & self , module : & str , name : & str ) -> InterpResult < ' tcx , u64 > {
87
87
// TODO: Cache the result.
88
88
self . eval_windows ( module, name) ?. to_u64 ( )
89
89
}
90
90
91
91
/// Helper function to get the `TyAndLayout` of a `libc` type
92
- fn libc_ty_layout ( & mut self , name : & str ) -> InterpResult < ' tcx , TyAndLayout < ' tcx > > {
93
- let this = self . eval_context_mut ( ) ;
92
+ fn libc_ty_layout ( & self , name : & str ) -> InterpResult < ' tcx , TyAndLayout < ' tcx > > {
93
+ let this = self . eval_context_ref ( ) ;
94
94
let ty = this. resolve_path ( & [ "libc" , name] ) . ty ( * this. tcx , ty:: ParamEnv :: reveal_all ( ) ) ;
95
95
this. layout_of ( ty)
96
96
}
97
97
98
98
/// Helper function to get the `TyAndLayout` of a `windows` type
99
- fn windows_ty_layout ( & mut self , name : & str ) -> InterpResult < ' tcx , TyAndLayout < ' tcx > > {
100
- let this = self . eval_context_mut ( ) ;
99
+ fn windows_ty_layout ( & self , name : & str ) -> InterpResult < ' tcx , TyAndLayout < ' tcx > > {
100
+ let this = self . eval_context_ref ( ) ;
101
101
let ty = this
102
102
. resolve_path ( & [ "std" , "sys" , "windows" , "c" , name] )
103
103
. ty ( * this. tcx , ty:: ParamEnv :: reveal_all ( ) ) ;
104
104
this. layout_of ( ty)
105
105
}
106
106
107
+ /// Project to the given *named* field of the mplace (which must be a struct or union type).
108
+ fn mplace_field_named (
109
+ & self ,
110
+ mplace : & MPlaceTy < ' tcx , Tag > ,
111
+ name : & str ,
112
+ ) -> InterpResult < ' tcx , MPlaceTy < ' tcx , Tag > > {
113
+ let this = self . eval_context_ref ( ) ;
114
+ let adt = mplace. layout . ty . ty_adt_def ( ) . unwrap ( ) ;
115
+ for ( idx, field) in adt. non_enum_variant ( ) . fields . iter ( ) . enumerate ( ) {
116
+ if field. name . as_str ( ) == name {
117
+ return this. mplace_field ( mplace, idx) ;
118
+ }
119
+ }
120
+ bug ! ( "No field named {} in type {}" , name, mplace. layout. ty) ;
121
+ }
122
+
123
+ /// Write an int of the appropriate size to `dest`. The target type may be signed or unsigned,
124
+ /// we try to do the right thing anyway. `i128` can fit all integer types except for `u128` so
125
+ /// this method is fine for almost all integer types.
126
+ fn write_int ( & mut self , i : impl Into < i128 > , dest : & PlaceTy < ' tcx , Tag > ) -> InterpResult < ' tcx > {
127
+ assert ! ( dest. layout. abi. is_scalar( ) , "write_int on non-scalar type {}" , dest. layout. ty) ;
128
+ let val = if dest. layout . abi . is_signed ( ) {
129
+ Scalar :: from_int ( i, dest. layout . size )
130
+ } else {
131
+ Scalar :: from_uint ( u64:: try_from ( i. into ( ) ) . unwrap ( ) , dest. layout . size )
132
+ } ;
133
+ self . eval_context_mut ( ) . write_scalar ( val, dest)
134
+ }
135
+
136
+ /// Write the first N fields of the given place.
137
+ fn write_int_fields (
138
+ & mut self ,
139
+ values : & [ i128 ] ,
140
+ dest : & MPlaceTy < ' tcx , Tag > ,
141
+ ) -> InterpResult < ' tcx > {
142
+ let this = self . eval_context_mut ( ) ;
143
+ for ( idx, & val) in values. iter ( ) . enumerate ( ) {
144
+ let field = this. mplace_field ( dest, idx) ?;
145
+ this. write_int ( val, & field. into ( ) ) ?;
146
+ }
147
+ Ok ( ( ) )
148
+ }
149
+
150
+ /// Write the given fields of the given place.
151
+ fn write_int_fields_named (
152
+ & mut self ,
153
+ values : & [ ( & str , i128 ) ] ,
154
+ dest : & MPlaceTy < ' tcx , Tag > ,
155
+ ) -> InterpResult < ' tcx > {
156
+ let this = self . eval_context_mut ( ) ;
157
+ for & ( name, val) in values. iter ( ) {
158
+ let field = this. mplace_field_named ( dest, name) ?;
159
+ this. write_int ( val, & field. into ( ) ) ?;
160
+ }
161
+ Ok ( ( ) )
162
+ }
163
+
107
164
/// Write a 0 of the appropriate size to `dest`.
108
165
fn write_null ( & mut self , dest : & PlaceTy < ' tcx , Tag > ) -> InterpResult < ' tcx > {
109
- self . eval_context_mut ( ) . write_scalar ( Scalar :: from_int ( 0 , dest . layout . size ) , dest)
166
+ self . write_int ( 0 , dest)
110
167
}
111
168
112
169
/// Test if this pointer equals 0.
@@ -373,27 +430,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
373
430
}
374
431
}
375
432
376
- // Writes several `ImmTy`s contiguously into memory. This is useful when you have to pack
377
- // different values into a struct.
378
- fn write_packed_immediates (
379
- & mut self ,
380
- place : & MPlaceTy < ' tcx , Tag > ,
381
- imms : & [ ImmTy < ' tcx , Tag > ] ,
382
- ) -> InterpResult < ' tcx > {
383
- let this = self . eval_context_mut ( ) ;
384
-
385
- let mut offset = Size :: from_bytes ( 0 ) ;
386
-
387
- for & imm in imms {
388
- this. write_immediate (
389
- * imm,
390
- & place. offset ( offset, MemPlaceMeta :: None , imm. layout , & * this. tcx ) ?. into ( ) ,
391
- ) ?;
392
- offset += imm. layout . size ;
393
- }
394
- Ok ( ( ) )
395
- }
396
-
397
433
/// Helper function used inside the shims of foreign functions to check that isolation is
398
434
/// disabled. It returns an error using the `name` of the foreign function if this is not the
399
435
/// case.
@@ -740,26 +776,6 @@ pub fn isolation_abort_error(name: &str) -> InterpResult<'static> {
740
776
) ) )
741
777
}
742
778
743
- pub fn immty_from_int_checked < ' tcx > (
744
- int : impl Into < i128 > ,
745
- layout : TyAndLayout < ' tcx > ,
746
- ) -> InterpResult < ' tcx , ImmTy < ' tcx , Tag > > {
747
- let int = int. into ( ) ;
748
- Ok ( ImmTy :: try_from_int ( int, layout) . ok_or_else ( || {
749
- err_unsup_format ! ( "signed value {:#x} does not fit in {} bits" , int, layout. size. bits( ) )
750
- } ) ?)
751
- }
752
-
753
- pub fn immty_from_uint_checked < ' tcx > (
754
- int : impl Into < u128 > ,
755
- layout : TyAndLayout < ' tcx > ,
756
- ) -> InterpResult < ' tcx , ImmTy < ' tcx , Tag > > {
757
- let int = int. into ( ) ;
758
- Ok ( ImmTy :: try_from_uint ( int, layout) . ok_or_else ( || {
759
- err_unsup_format ! ( "unsigned value {:#x} does not fit in {} bits" , int, layout. size. bits( ) )
760
- } ) ?)
761
- }
762
-
763
779
pub fn bool_to_simd_element ( b : bool , size : Size ) -> Scalar < Tag > {
764
780
// SIMD uses all-1 as pattern for "true"
765
781
let val = if b { -1 } else { 0 } ;
0 commit comments