@@ -2,12 +2,13 @@ use rustc::hir::def_id::DefId;
2
2
use rustc:: mir:: repr as mir;
3
3
use rustc:: ty:: layout:: Layout ;
4
4
use rustc:: ty:: subst:: Substs ;
5
- use rustc:: ty;
5
+ use rustc:: ty:: { self , Ty } ;
6
6
7
7
use error:: { EvalError , EvalResult } ;
8
8
use memory:: Pointer ;
9
9
use interpreter:: EvalContext ;
10
- use primval;
10
+ use primval:: { self , PrimVal } ;
11
+ use interpreter:: value:: Value ;
11
12
12
13
impl < ' a , ' tcx > EvalContext < ' a , ' tcx > {
13
14
pub ( super ) fn call_intrinsic (
@@ -16,29 +17,35 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
16
17
substs : & ' tcx Substs < ' tcx > ,
17
18
args : & [ mir:: Operand < ' tcx > ] ,
18
19
dest : Pointer ,
20
+ dest_ty : Ty < ' tcx > ,
19
21
dest_layout : & ' tcx Layout ,
20
22
) -> EvalResult < ' tcx , ( ) > {
21
- // TODO(solson): We can probably remove this _to_ptr easily.
22
- let args_res: EvalResult < Vec < Pointer > > = args. iter ( )
23
- . map ( |arg| self . eval_operand_to_ptr ( arg) )
23
+ let args_ptrs: EvalResult < Vec < Value > > = args. iter ( )
24
+ . map ( |arg| self . eval_operand ( arg) )
24
25
. collect ( ) ;
25
- let args_ptrs = args_res ?;
26
+ let args_ptrs = args_ptrs ?;
26
27
let pointer_size = self . memory . pointer_size ( ) ;
28
+ let i32 = self . tcx . types . i32 ;
29
+ let isize = self . tcx . types . isize ;
30
+ let usize = self . tcx . types . usize ;
31
+ let f32 = self . tcx . types . f32 ;
32
+ let f64 = self . tcx . types . f64 ;
27
33
28
34
match & self . tcx . item_name ( def_id) . as_str ( ) [ ..] {
29
35
"add_with_overflow" => self . intrinsic_with_overflow ( mir:: BinOp :: Add , & args[ 0 ] , & args[ 1 ] , dest, dest_layout) ?,
30
36
"sub_with_overflow" => self . intrinsic_with_overflow ( mir:: BinOp :: Sub , & args[ 0 ] , & args[ 1 ] , dest, dest_layout) ?,
31
37
"mul_with_overflow" => self . intrinsic_with_overflow ( mir:: BinOp :: Mul , & args[ 0 ] , & args[ 1 ] , dest, dest_layout) ?,
32
38
33
39
"arith_offset" => {
34
- let ptr = self . memory . read_ptr ( args_ptrs[ 0 ] ) ?;
35
- let offset = self . memory . read_int ( args_ptrs[ 1 ] , pointer_size ) ? ;
40
+ let ptr = args_ptrs[ 0 ] . read_ptr ( & self . memory ) ?;
41
+ let offset = self . value_to_primval ( args_ptrs[ 1 ] , isize ) ? . expect_int ( "arith_offset second arg not isize" ) ;
36
42
let new_ptr = ptr. offset ( offset as isize ) ;
37
43
self . memory . write_ptr ( dest, new_ptr) ?;
38
44
}
39
45
40
46
"assume" => {
41
- if !self . memory . read_bool ( args_ptrs[ 0 ] ) ? {
47
+ let bool = self . tcx . types . bool ;
48
+ if !self . value_to_primval ( args_ptrs[ 0 ] , bool) ?. expect_bool ( "assume arg not bool" ) {
42
49
return Err ( EvalError :: AssumptionNotHeld ) ;
43
50
}
44
51
}
@@ -51,47 +58,59 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
51
58
let elem_ty = substs. type_at ( 0 ) ;
52
59
let elem_size = self . type_size ( elem_ty) ;
53
60
let elem_align = self . type_align ( elem_ty) ;
54
- let src = self . memory . read_ptr ( args_ptrs[ 0 ] ) ?;
55
- let dest = self . memory . read_ptr ( args_ptrs[ 1 ] ) ?;
56
- let count = self . memory . read_isize ( args_ptrs[ 2 ] ) ? ;
61
+ let src = args_ptrs[ 0 ] . read_ptr ( & self . memory ) ?;
62
+ let dest = args_ptrs[ 1 ] . read_ptr ( & self . memory ) ?;
63
+ let count = self . value_to_primval ( args_ptrs[ 2 ] , usize ) ? . expect_uint ( "arith_offset second arg not isize" ) ;
57
64
self . memory . copy ( src, dest, count as usize * elem_size, elem_align) ?;
58
65
}
59
66
60
67
"ctpop" => {
61
68
let elem_ty = substs. type_at ( 0 ) ;
62
69
let elem_size = self . type_size ( elem_ty) ;
63
- let num = self . memory . read_uint ( args_ptrs[ 0 ] , elem_size) ?. count_ones ( ) ;
70
+ let num = self . value_to_primval ( args_ptrs[ 2 ] , elem_ty) ?. expect_int ( "ctpop second arg not integral" ) ;
71
+ let num = num. count_ones ( ) ;
64
72
self . memory . write_uint ( dest, num. into ( ) , elem_size) ?;
65
73
}
66
74
67
75
"ctlz" => {
68
76
let elem_ty = substs. type_at ( 0 ) ;
69
77
let elem_size = self . type_size ( elem_ty) ;
70
- let num = self . memory . read_uint ( args_ptrs[ 0 ] , elem_size) ?. leading_zeros ( ) ;
78
+ let num = self . value_to_primval ( args_ptrs[ 2 ] , elem_ty) ?;
79
+ let num = match num {
80
+ PrimVal :: I8 ( i) => i. leading_zeros ( ) ,
81
+ PrimVal :: U8 ( i) => i. leading_zeros ( ) ,
82
+ PrimVal :: I16 ( i) => i. leading_zeros ( ) ,
83
+ PrimVal :: U16 ( i) => i. leading_zeros ( ) ,
84
+ PrimVal :: I32 ( i) => i. leading_zeros ( ) ,
85
+ PrimVal :: U32 ( i) => i. leading_zeros ( ) ,
86
+ PrimVal :: I64 ( i) => i. leading_zeros ( ) ,
87
+ PrimVal :: U64 ( i) => i. leading_zeros ( ) ,
88
+ _ => bug ! ( "ctlz called with non-integer type" ) ,
89
+ } ;
71
90
self . memory . write_uint ( dest, num. into ( ) , elem_size) ?;
72
91
}
73
92
74
93
"discriminant_value" => {
75
94
let ty = substs. type_at ( 0 ) ;
76
- let adt_ptr = self . memory . read_ptr ( args_ptrs[ 0 ] ) ?;
95
+ let adt_ptr = args_ptrs[ 0 ] . read_ptr ( & self . memory ) ?;
77
96
let discr_val = self . read_discriminant_value ( adt_ptr, ty) ?;
78
97
self . memory . write_uint ( dest, discr_val, 8 ) ?;
79
98
}
80
99
81
100
"fabsf32" => {
82
- let f = self . memory . read_f32 ( args_ptrs[ 0 ] ) ? ;
101
+ let f = self . value_to_primval ( args_ptrs[ 2 ] , f32 ) ? . expect_f32 ( "fabsf32 read non f32" ) ;
83
102
self . memory . write_f32 ( dest, f. abs ( ) ) ?;
84
103
}
85
104
86
105
"fabsf64" => {
87
- let f = self . memory . read_f64 ( args_ptrs[ 0 ] ) ? ;
106
+ let f = self . value_to_primval ( args_ptrs[ 2 ] , f64 ) ? . expect_f64 ( "fabsf64 read non f64" ) ;
88
107
self . memory . write_f64 ( dest, f. abs ( ) ) ?;
89
108
}
90
109
91
110
"fadd_fast" => {
92
111
let ty = substs. type_at ( 0 ) ;
93
- let a = self . read_primval ( args_ptrs[ 0 ] , ty) ?;
94
- let b = self . read_primval ( args_ptrs[ 0 ] , ty) ?;
112
+ let a = self . value_to_primval ( args_ptrs[ 0 ] , ty) ?;
113
+ let b = self . value_to_primval ( args_ptrs[ 0 ] , ty) ?;
95
114
let result = primval:: binary_op ( mir:: BinOp :: Add , a, b) ?;
96
115
self . memory . write_primval ( dest, result. 0 ) ?;
97
116
}
@@ -117,8 +136,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
117
136
118
137
"move_val_init" => {
119
138
let ty = substs. type_at ( 0 ) ;
120
- let ptr = self . memory . read_ptr ( args_ptrs[ 0 ] ) ?;
121
- self . move_ ( args_ptrs[ 1 ] , ptr, ty) ?;
139
+ let ptr = args_ptrs[ 0 ] . read_ptr ( & self . memory ) ?;
140
+ self . write_value ( args_ptrs[ 1 ] , ptr, ty) ?;
122
141
}
123
142
124
143
"needs_drop" => {
@@ -129,10 +148,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
129
148
"offset" => {
130
149
let pointee_ty = substs. type_at ( 0 ) ;
131
150
let pointee_size = self . type_size ( pointee_ty) as isize ;
132
- let ptr_arg = args_ptrs[ 0 ] ;
133
- let offset = self . memory . read_isize ( args_ptrs[ 1 ] ) ?;
151
+ let offset = self . value_to_primval ( args_ptrs[ 1 ] , isize) ?. expect_int ( "offset second arg not isize" ) ;
134
152
135
- let ptr = self . memory . read_ptr ( ptr_arg ) ?;
153
+ let ptr = args_ptrs [ 0 ] . read_ptr ( & self . memory ) ?;
136
154
let result_ptr = ptr. offset ( offset as isize * pointee_size) ;
137
155
self . memory . write_ptr ( dest, result_ptr) ?;
138
156
}
@@ -150,24 +168,24 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
150
168
}
151
169
152
170
"powif32" => {
153
- let f = self . memory . read_f32 ( args_ptrs[ 0 ] ) ? ;
154
- let i = self . memory . read_int ( args_ptrs[ 1 ] , 4 ) ? ;
171
+ let f = self . value_to_primval ( args_ptrs[ 0 ] , f32 ) ? . expect_f32 ( "powif32 first arg not f32" ) ;
172
+ let i = self . value_to_primval ( args_ptrs[ 1 ] , i32 ) ? . expect_int ( "powif32 second arg not i32" ) ;
155
173
self . memory . write_f32 ( dest, f. powi ( i as i32 ) ) ?;
156
174
}
157
175
158
176
"powif64" => {
159
- let f = self . memory . read_f32 ( args_ptrs[ 0 ] ) ? ;
160
- let i = self . memory . read_int ( args_ptrs[ 1 ] , 4 ) ? ;
161
- self . memory . write_f32 ( dest, f. powi ( i as i32 ) ) ?;
177
+ let f = self . value_to_primval ( args_ptrs[ 0 ] , f64 ) ? . expect_f64 ( "powif64 first arg not f64" ) ;
178
+ let i = self . value_to_primval ( args_ptrs[ 1 ] , i32 ) ? . expect_int ( "powif64 second arg not i32" ) ;
179
+ self . memory . write_f64 ( dest, f. powi ( i as i32 ) ) ?;
162
180
}
163
181
164
182
"sqrtf32" => {
165
- let f = self . memory . read_f32 ( args_ptrs[ 0 ] ) ? ;
183
+ let f = self . value_to_primval ( args_ptrs[ 0 ] , f32 ) ? . expect_f32 ( "sqrtf32 first arg not f32" ) ;
166
184
self . memory . write_f32 ( dest, f. sqrt ( ) ) ?;
167
185
}
168
186
169
187
"sqrtf64" => {
170
- let f = self . memory . read_f64 ( args_ptrs[ 0 ] ) ? ;
188
+ let f = self . value_to_primval ( args_ptrs[ 0 ] , f64 ) ? . expect_f64 ( "sqrtf64 first arg not f64" ) ;
171
189
self . memory . write_f64 ( dest, f. sqrt ( ) ) ?;
172
190
}
173
191
@@ -182,14 +200,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
182
200
let ( size, _) = self . size_and_align_of_dst ( ty, args_ptrs[ 0 ] ) ?;
183
201
self . memory . write_uint ( dest, size, pointer_size) ?;
184
202
}
185
- // FIXME: wait for eval_operand_to_ptr to be gone
186
- /*
187
203
"type_name" => {
188
204
let ty = substs. type_at ( 0 ) ;
189
205
let ty_name = ty. to_string ( ) ;
190
206
let s = self . str_to_value ( & ty_name) ?;
191
- self.memory.write_ptr( dest, s )?;
192
- }*/
207
+ self . write_value ( s , dest, dest_ty ) ?;
208
+ }
193
209
"type_id" => {
194
210
let ty = substs. type_at ( 0 ) ;
195
211
let n = self . tcx . type_id_hash ( ty) ;
@@ -198,7 +214,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
198
214
199
215
"transmute" => {
200
216
let ty = substs. type_at ( 0 ) ;
201
- self . move_ ( args_ptrs[ 0 ] , dest, ty) ?;
217
+ self . write_value ( args_ptrs[ 0 ] , dest, ty) ?;
202
218
}
203
219
204
220
"try" => unimplemented ! ( ) ,
@@ -207,14 +223,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
207
223
208
224
"volatile_load" => {
209
225
let ty = substs. type_at ( 0 ) ;
210
- let ptr = self . memory . read_ptr ( args_ptrs[ 0 ] ) ?;
226
+ let ptr = args_ptrs[ 0 ] . read_ptr ( & self . memory ) ?;
211
227
self . move_ ( ptr, dest, ty) ?;
212
228
}
213
229
214
230
"volatile_store" => {
215
231
let ty = substs. type_at ( 0 ) ;
216
- let dest = self . memory . read_ptr ( args_ptrs[ 0 ] ) ?;
217
- self . move_ ( args_ptrs[ 1 ] , dest, ty) ?;
232
+ let dest = args_ptrs[ 0 ] . read_ptr ( & self . memory ) ?;
233
+ self . write_value ( args_ptrs[ 1 ] , dest, ty) ?;
218
234
}
219
235
220
236
name => return Err ( EvalError :: Unimplemented ( format ! ( "unimplemented intrinsic: {}" , name) ) ) ,
@@ -229,7 +245,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
229
245
fn size_and_align_of_dst (
230
246
& self ,
231
247
ty : ty:: Ty < ' tcx > ,
232
- value : Pointer ,
248
+ value : Value ,
233
249
) -> EvalResult < ' tcx , ( u64 , u64 ) > {
234
250
let pointer_size = self . memory . pointer_size ( ) ;
235
251
if self . type_is_sized ( ty) {
@@ -306,8 +322,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
306
322
}
307
323
}
308
324
ty:: TyTrait ( ..) => {
309
- let ( _, vtable) = self . get_fat_ptr ( value) ;
310
- let vtable = self . memory . read_ptr ( vtable) ?;
325
+ let vtable = value. expect_vtable ( & self . memory ) ?;
311
326
// the second entry in the vtable is the dynamic size of the object.
312
327
let size = self . memory . read_usize ( vtable. offset ( pointer_size as isize ) ) ?;
313
328
let align = self . memory . read_usize ( vtable. offset ( pointer_size as isize * 2 ) ) ?;
@@ -317,10 +332,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
317
332
ty:: TySlice ( _) | ty:: TyStr => {
318
333
let elem_ty = ty. sequence_element_type ( self . tcx ) ;
319
334
let elem_size = self . type_size ( elem_ty) as u64 ;
320
- let ( _, len_ptr) = self . get_fat_ptr ( value) ;
321
- let n = self . memory . read_usize ( len_ptr) ?;
335
+ let len = value. expect_slice_len ( & self . memory ) ?;
322
336
let align = self . type_align ( elem_ty) ;
323
- Ok ( ( n * elem_size, align as u64 ) )
337
+ Ok ( ( len * elem_size, align as u64 ) )
324
338
}
325
339
326
340
_ => bug ! ( "size_of_val::<{:?}>" , ty) ,
0 commit comments