@@ -5,10 +5,13 @@ use rustc_middle::{mir, ty};
55use super :: check_intrinsic_arg_count;
66use crate :: * ;
77
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+ } ,
1215 Max ,
1316 Min ,
1417}
@@ -106,55 +109,85 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
106109
107110 "or" => {
108111 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+ ) ?;
110118 }
111119 "xor" => {
112120 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+ ) ?;
114127 }
115128 "and" => {
116129 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+ ) ?;
118136 }
119137 "nand" => {
120138 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+ ) ?;
122145 }
123146 "xadd" => {
124147 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+ ) ?;
126154 }
127155 "xsub" => {
128156 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+ ) ?;
130163 }
131164 "min" => {
132165 let ord = get_ord_at ( 1 ) ;
133166 // Later we will use the type to indicate signed vs unsigned,
134167 // so make sure it matches the intrinsic name.
135168 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) ) ?;
137170 }
138171 "umin" => {
139172 let ord = get_ord_at ( 1 ) ;
140173 // Later we will use the type to indicate signed vs unsigned,
141174 // so make sure it matches the intrinsic name.
142175 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) ) ?;
144177 }
145178 "max" => {
146179 let ord = get_ord_at ( 1 ) ;
147180 // Later we will use the type to indicate signed vs unsigned,
148181 // so make sure it matches the intrinsic name.
149182 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) ) ?;
151184 }
152185 "umax" => {
153186 let ord = get_ord_at ( 1 ) ;
154187 // Later we will use the type to indicate signed vs unsigned,
155188 // so make sure it matches the intrinsic name.
156189 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) ) ?;
158191 }
159192
160193 _ => return interp_ok ( EmulateItemResult :: NotSupported ) ,
@@ -222,8 +255,8 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
222255 & mut self ,
223256 args : & [ OpTy < ' tcx > ] ,
224257 dest : & MPlaceTy < ' tcx > ,
225- atomic_op : AtomicOp ,
226- atomic : AtomicRwOrd ,
258+ atomic_op : AtomicRmwOp ,
259+ ord : AtomicRwOrd ,
227260 ) -> InterpResult < ' tcx > {
228261 let this = self . eval_context_mut ( ) ;
229262
@@ -240,14 +273,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
240273 ) ;
241274 }
242275
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) ?;
251277 this. write_immediate ( * old, dest) ?; // old value is returned
252278 interp_ok ( ( ) )
253279 }
0 commit comments