@@ -78,7 +78,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
78
78
// we are inherently singlethreaded and singlecored, this is a nop
79
79
}
80
80
81
- "atomic_xchg" => {
81
+ _ if intrinsic_name . starts_with ( "atomic_xchg" ) => {
82
82
let ty = substs. type_at ( 0 ) ;
83
83
let ptr = arg_vals[ 0 ] . read_ptr ( & self . memory ) ?;
84
84
let change = self . value_to_primval ( arg_vals[ 1 ] , ty) ?;
@@ -92,8 +92,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
92
92
self . write_primval ( Lvalue :: from_ptr ( ptr) , change, ty) ?;
93
93
}
94
94
95
- "atomic_cxchg_relaxed" |
96
- "atomic_cxchg" => {
95
+ _ if intrinsic_name. starts_with ( "atomic_cxchg" ) => {
97
96
let ty = substs. type_at ( 0 ) ;
98
97
let ptr = arg_vals[ 0 ] . read_ptr ( & self . memory ) ?;
99
98
let expect_old = self . value_to_primval ( arg_vals[ 1 ] , ty) ?;
@@ -111,8 +110,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
111
110
self . write_primval ( Lvalue :: from_ptr ( ptr) , change, ty) ?;
112
111
}
113
112
114
- "atomic_xadd" |
115
- "atomic_xadd_relaxed" => {
113
+ "atomic_or" | "atomic_or_acq" | "atomic_or_rel" | "atomic_or_acqrel" | "atomic_or_relaxed" |
114
+ "atomic_xor" | "atomic_xor_acq" | "atomic_xor_rel" | "atomic_xor_acqrel" | "atomic_xor_relaxed" |
115
+ "atomic_and" | "atomic_and_acq" | "atomic_and_rel" | "atomic_and_acqrel" | "atomic_and_relaxed" |
116
+ "atomic_xadd" | "atomic_xadd_acq" | "atomic_xadd_rel" | "atomic_xadd_acqrel" | "atomic_xadd_relaxed" |
117
+ "atomic_xsub" | "atomic_xsub_acq" | "atomic_xsub_rel" | "atomic_xsub_acqrel" | "atomic_xsub_relaxed" => {
116
118
let ty = substs. type_at ( 0 ) ;
117
119
let ptr = arg_vals[ 0 ] . read_ptr ( & self . memory ) ?;
118
120
let change = self . value_to_primval ( arg_vals[ 1 ] , ty) ?;
@@ -124,27 +126,18 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
124
126
} ;
125
127
self . write_primval ( dest, old, ty) ?;
126
128
let kind = self . ty_to_primval_kind ( ty) ?;
127
- // FIXME: what do atomics do on overflow?
128
- let ( val, _) = operator:: binary_op ( mir:: BinOp :: Add , old, kind, change, kind) ?;
129
- self . write_primval ( Lvalue :: from_ptr ( ptr) , val, ty) ?;
130
- } ,
131
-
132
- "atomic_xsub_rel" => {
133
- let ty = substs. type_at ( 0 ) ;
134
- let ptr = arg_vals[ 0 ] . read_ptr ( & self . memory ) ?;
135
- let change = self . value_to_primval ( arg_vals[ 1 ] , ty) ?;
136
- let old = self . read_value ( ptr, ty) ?;
137
- let old = match old {
138
- Value :: ByVal ( val) => val,
139
- Value :: ByRef ( _) => bug ! ( "just read the value, can't be byref" ) ,
140
- Value :: ByValPair ( ..) => bug ! ( "atomic_xsub_rel doesn't work with nonprimitives" ) ,
129
+ let op = match intrinsic_name. split ( '_' ) . nth ( 1 ) . unwrap ( ) {
130
+ "or" => mir:: BinOp :: BitOr ,
131
+ "xor" => mir:: BinOp :: BitXor ,
132
+ "and" => mir:: BinOp :: BitAnd ,
133
+ "xadd" => mir:: BinOp :: Add ,
134
+ "xsub" => mir:: BinOp :: Sub ,
135
+ _ => bug ! ( ) ,
141
136
} ;
142
- self . write_primval ( dest, old, ty) ?;
143
- let kind = self . ty_to_primval_kind ( ty) ?;
144
137
// FIXME: what do atomics do on overflow?
145
- let ( val, _) = operator:: binary_op ( mir :: BinOp :: Sub , old, kind, change, kind) ?;
138
+ let ( val, _) = operator:: binary_op ( op , old, kind, change, kind) ?;
146
139
self . write_primval ( Lvalue :: from_ptr ( ptr) , val, ty) ?;
147
- }
140
+ } ,
148
141
149
142
"breakpoint" => unimplemented ! ( ) , // halt miri
150
143
@@ -207,14 +200,50 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
207
200
return self . eval_drop_impls ( drops, span) ;
208
201
}
209
202
210
- "fabsf32" => {
203
+ "sinf32" | "fabsf32" | "cosf32" |
204
+ "sqrtf32" | "expf32" | "exp2f32" |
205
+ "logf32" | "log10f32" | "log2f32" |
206
+ "floorf32" | "ceilf32" | "truncf32" => {
211
207
let f = self . value_to_primval ( arg_vals[ 0 ] , f32) ?. to_f32 ( ) ?;
212
- self . write_primval ( dest, PrimVal :: from_f32 ( f. abs ( ) ) , dest_ty) ?;
208
+ let f = match intrinsic_name {
209
+ "sinf32" => f. sin ( ) ,
210
+ "fabsf32" => f. abs ( ) ,
211
+ "cosf32" => f. cos ( ) ,
212
+ "sqrtf32" => f. sqrt ( ) ,
213
+ "expf32" => f. exp ( ) ,
214
+ "exp2f32" => f. exp2 ( ) ,
215
+ "logf32" => f. ln ( ) ,
216
+ "log10f32" => f. log10 ( ) ,
217
+ "log2f32" => f. log2 ( ) ,
218
+ "floorf32" => f. floor ( ) ,
219
+ "ceilf32" => f. ceil ( ) ,
220
+ "truncf32" => f. trunc ( ) ,
221
+ _ => bug ! ( ) ,
222
+ } ;
223
+ self . write_primval ( dest, PrimVal :: from_f32 ( f) , dest_ty) ?;
213
224
}
214
225
215
- "fabsf64" => {
226
+ "sinf64" | "fabsf64" | "cosf64" |
227
+ "sqrtf64" | "expf64" | "exp2f64" |
228
+ "logf64" | "log10f64" | "log2f64" |
229
+ "floorf64" | "ceilf64" | "truncf64" => {
216
230
let f = self . value_to_primval ( arg_vals[ 0 ] , f64) ?. to_f64 ( ) ?;
217
- self . write_primval ( dest, PrimVal :: from_f64 ( f. abs ( ) ) , dest_ty) ?;
231
+ let f = match intrinsic_name {
232
+ "sinf64" => f. sin ( ) ,
233
+ "fabsf64" => f. abs ( ) ,
234
+ "cosf64" => f. cos ( ) ,
235
+ "sqrtf64" => f. sqrt ( ) ,
236
+ "expf64" => f. exp ( ) ,
237
+ "exp2f64" => f. exp2 ( ) ,
238
+ "logf64" => f. ln ( ) ,
239
+ "log10f64" => f. log10 ( ) ,
240
+ "log2f64" => f. log2 ( ) ,
241
+ "floorf64" => f. floor ( ) ,
242
+ "ceilf64" => f. ceil ( ) ,
243
+ "truncf64" => f. trunc ( ) ,
244
+ _ => bug ! ( ) ,
245
+ } ;
246
+ self . write_primval ( dest, PrimVal :: from_f64 ( f) , dest_ty) ?;
218
247
}
219
248
220
249
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
@@ -320,26 +349,42 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
320
349
self . intrinsic_overflowing ( mir:: BinOp :: Add , & args[ 0 ] , & args[ 1 ] , dest, dest_ty) ?;
321
350
}
322
351
323
- "powif32 " => {
352
+ "powf32 " => {
324
353
let f = self . value_to_primval ( arg_vals[ 0 ] , f32) ?. to_f32 ( ) ?;
325
- let i = self . value_to_primval ( arg_vals[ 1 ] , i32 ) ?. to_i128 ( ) ?;
326
- self . write_primval ( dest, PrimVal :: from_f32 ( f. powi ( i as i32 ) ) , dest_ty) ?;
354
+ let f2 = self . value_to_primval ( arg_vals[ 1 ] , f32 ) ?. to_f32 ( ) ?;
355
+ self . write_primval ( dest, PrimVal :: from_f32 ( f. powf ( f2 ) ) , dest_ty) ?;
327
356
}
328
357
329
- "powif64 " => {
358
+ "powf64 " => {
330
359
let f = self . value_to_primval ( arg_vals[ 0 ] , f64) ?. to_f64 ( ) ?;
331
- let i = self . value_to_primval ( arg_vals[ 1 ] , i32) ?. to_i128 ( ) ?;
332
- self . write_primval ( dest, PrimVal :: from_f64 ( f. powi ( i as i32 ) ) , dest_ty) ?;
360
+ let f2 = self . value_to_primval ( arg_vals[ 1 ] , f64) ?. to_f64 ( ) ?;
361
+ self . write_primval ( dest, PrimVal :: from_f64 ( f. powf ( f2) ) , dest_ty) ?;
362
+ }
363
+
364
+ "fmaf32" => {
365
+ let a = self . value_to_primval ( arg_vals[ 0 ] , f32) ?. to_f32 ( ) ?;
366
+ let b = self . value_to_primval ( arg_vals[ 1 ] , f32) ?. to_f32 ( ) ?;
367
+ let c = self . value_to_primval ( arg_vals[ 2 ] , f32) ?. to_f32 ( ) ?;
368
+ self . write_primval ( dest, PrimVal :: from_f32 ( a * b + c) , dest_ty) ?;
369
+ }
370
+
371
+ "fmaf64" => {
372
+ let a = self . value_to_primval ( arg_vals[ 0 ] , f64) ?. to_f64 ( ) ?;
373
+ let b = self . value_to_primval ( arg_vals[ 1 ] , f64) ?. to_f64 ( ) ?;
374
+ let c = self . value_to_primval ( arg_vals[ 2 ] , f64) ?. to_f64 ( ) ?;
375
+ self . write_primval ( dest, PrimVal :: from_f64 ( a * b + c) , dest_ty) ?;
333
376
}
334
377
335
- "sqrtf32 " => {
378
+ "powif32 " => {
336
379
let f = self . value_to_primval ( arg_vals[ 0 ] , f32) ?. to_f32 ( ) ?;
337
- self . write_primval ( dest, PrimVal :: from_f32 ( f. sqrt ( ) ) , dest_ty) ?;
380
+ let i = self . value_to_primval ( arg_vals[ 1 ] , i32) ?. to_i128 ( ) ?;
381
+ self . write_primval ( dest, PrimVal :: from_f32 ( f. powi ( i as i32 ) ) , dest_ty) ?;
338
382
}
339
383
340
- "sqrtf64 " => {
384
+ "powif64 " => {
341
385
let f = self . value_to_primval ( arg_vals[ 0 ] , f64) ?. to_f64 ( ) ?;
342
- self . write_primval ( dest, PrimVal :: from_f64 ( f. sqrt ( ) ) , dest_ty) ?;
386
+ let i = self . value_to_primval ( arg_vals[ 1 ] , i32) ?. to_i128 ( ) ?;
387
+ self . write_primval ( dest, PrimVal :: from_f64 ( f. powi ( i as i32 ) ) , dest_ty) ?;
343
388
}
344
389
345
390
"size_of" => {
0 commit comments