@@ -5,10 +5,13 @@ use rustc_middle::{mir, ty};
5
5
use super :: check_intrinsic_arg_count;
6
6
use crate :: * ;
7
7
8
- pub enum AtomicOp {
9
- /// The `bool` indicates whether the result of the operation should be negated (`UnOp::Not`,
10
- /// must be a boolean-typed operation).
11
- MirOp ( mir:: BinOp , bool ) ,
8
+ pub enum AtomicRmwOp {
9
+ MirOp {
10
+ op : mir:: BinOp ,
11
+ /// Indicates whether the result of the operation should be negated (`UnOp::Not`, must be a
12
+ /// boolean-typed operation).
13
+ neg : bool ,
14
+ } ,
12
15
Max ,
13
16
Min ,
14
17
}
@@ -106,55 +109,85 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
106
109
107
110
"or" => {
108
111
let ord = get_ord_at ( 2 ) ;
109
- this. atomic_rmw_op ( args, dest, AtomicOp :: MirOp ( BinOp :: BitOr , false ) , rw_ord ( ord) ) ?;
112
+ this. atomic_rmw_op (
113
+ args,
114
+ dest,
115
+ AtomicRmwOp :: MirOp { op : BinOp :: BitOr , neg : false } ,
116
+ rw_ord ( ord) ,
117
+ ) ?;
110
118
}
111
119
"xor" => {
112
120
let ord = get_ord_at ( 2 ) ;
113
- this. atomic_rmw_op ( args, dest, AtomicOp :: MirOp ( BinOp :: BitXor , false ) , rw_ord ( ord) ) ?;
121
+ this. atomic_rmw_op (
122
+ args,
123
+ dest,
124
+ AtomicRmwOp :: MirOp { op : BinOp :: BitXor , neg : false } ,
125
+ rw_ord ( ord) ,
126
+ ) ?;
114
127
}
115
128
"and" => {
116
129
let ord = get_ord_at ( 2 ) ;
117
- this. atomic_rmw_op ( args, dest, AtomicOp :: MirOp ( BinOp :: BitAnd , false ) , rw_ord ( ord) ) ?;
130
+ this. atomic_rmw_op (
131
+ args,
132
+ dest,
133
+ AtomicRmwOp :: MirOp { op : BinOp :: BitAnd , neg : false } ,
134
+ rw_ord ( ord) ,
135
+ ) ?;
118
136
}
119
137
"nand" => {
120
138
let ord = get_ord_at ( 2 ) ;
121
- this. atomic_rmw_op ( args, dest, AtomicOp :: MirOp ( BinOp :: BitAnd , true ) , rw_ord ( ord) ) ?;
139
+ this. atomic_rmw_op (
140
+ args,
141
+ dest,
142
+ AtomicRmwOp :: MirOp { op : BinOp :: BitAnd , neg : true } ,
143
+ rw_ord ( ord) ,
144
+ ) ?;
122
145
}
123
146
"xadd" => {
124
147
let ord = get_ord_at ( 2 ) ;
125
- this. atomic_rmw_op ( args, dest, AtomicOp :: MirOp ( BinOp :: Add , false ) , rw_ord ( ord) ) ?;
148
+ this. atomic_rmw_op (
149
+ args,
150
+ dest,
151
+ AtomicRmwOp :: MirOp { op : BinOp :: Add , neg : false } ,
152
+ rw_ord ( ord) ,
153
+ ) ?;
126
154
}
127
155
"xsub" => {
128
156
let ord = get_ord_at ( 2 ) ;
129
- this. atomic_rmw_op ( args, dest, AtomicOp :: MirOp ( BinOp :: Sub , false ) , rw_ord ( ord) ) ?;
157
+ this. atomic_rmw_op (
158
+ args,
159
+ dest,
160
+ AtomicRmwOp :: MirOp { op : BinOp :: Sub , neg : false } ,
161
+ rw_ord ( ord) ,
162
+ ) ?;
130
163
}
131
164
"min" => {
132
165
let ord = get_ord_at ( 1 ) ;
133
166
// Later we will use the type to indicate signed vs unsigned,
134
167
// so make sure it matches the intrinsic name.
135
168
assert ! ( matches!( args[ 1 ] . layout. ty. kind( ) , ty:: Int ( _) ) ) ;
136
- this. atomic_rmw_op ( args, dest, AtomicOp :: Min , rw_ord ( ord) ) ?;
169
+ this. atomic_rmw_op ( args, dest, AtomicRmwOp :: Min , rw_ord ( ord) ) ?;
137
170
}
138
171
"umin" => {
139
172
let ord = get_ord_at ( 1 ) ;
140
173
// Later we will use the type to indicate signed vs unsigned,
141
174
// so make sure it matches the intrinsic name.
142
175
assert ! ( matches!( args[ 1 ] . layout. ty. kind( ) , ty:: Uint ( _) ) ) ;
143
- this. atomic_rmw_op ( args, dest, AtomicOp :: Min , rw_ord ( ord) ) ?;
176
+ this. atomic_rmw_op ( args, dest, AtomicRmwOp :: Min , rw_ord ( ord) ) ?;
144
177
}
145
178
"max" => {
146
179
let ord = get_ord_at ( 1 ) ;
147
180
// Later we will use the type to indicate signed vs unsigned,
148
181
// so make sure it matches the intrinsic name.
149
182
assert ! ( matches!( args[ 1 ] . layout. ty. kind( ) , ty:: Int ( _) ) ) ;
150
- this. atomic_rmw_op ( args, dest, AtomicOp :: Max , rw_ord ( ord) ) ?;
183
+ this. atomic_rmw_op ( args, dest, AtomicRmwOp :: Max , rw_ord ( ord) ) ?;
151
184
}
152
185
"umax" => {
153
186
let ord = get_ord_at ( 1 ) ;
154
187
// Later we will use the type to indicate signed vs unsigned,
155
188
// so make sure it matches the intrinsic name.
156
189
assert ! ( matches!( args[ 1 ] . layout. ty. kind( ) , ty:: Uint ( _) ) ) ;
157
- this. atomic_rmw_op ( args, dest, AtomicOp :: Max , rw_ord ( ord) ) ?;
190
+ this. atomic_rmw_op ( args, dest, AtomicRmwOp :: Max , rw_ord ( ord) ) ?;
158
191
}
159
192
160
193
_ => return interp_ok ( EmulateItemResult :: NotSupported ) ,
@@ -222,8 +255,8 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
222
255
& mut self ,
223
256
args : & [ OpTy < ' tcx > ] ,
224
257
dest : & MPlaceTy < ' tcx > ,
225
- atomic_op : AtomicOp ,
226
- atomic : AtomicRwOrd ,
258
+ atomic_op : AtomicRmwOp ,
259
+ ord : AtomicRwOrd ,
227
260
) -> InterpResult < ' tcx > {
228
261
let this = self . eval_context_mut ( ) ;
229
262
@@ -240,14 +273,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
240
273
) ;
241
274
}
242
275
243
- let old = match atomic_op {
244
- AtomicOp :: Min =>
245
- this. atomic_min_max_scalar ( & place, rhs, /* min */ true , atomic) ?,
246
- AtomicOp :: Max =>
247
- this. atomic_min_max_scalar ( & place, rhs, /* min */ false , atomic) ?,
248
- AtomicOp :: MirOp ( op, not) =>
249
- this. atomic_rmw_op_immediate ( & place, & rhs, op, not, atomic) ?,
250
- } ;
276
+ let old = this. atomic_rmw_op_immediate ( & place, & rhs, atomic_op, ord) ?;
251
277
this. write_immediate ( * old, dest) ?; // old value is returned
252
278
interp_ok ( ( ) )
253
279
}
0 commit comments