@@ -92,6 +92,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
9292 let invalid_monomorphization_int_type = |ty| {
9393 bx. tcx ( ) . dcx ( ) . emit_err ( InvalidMonomorphization :: BasicIntegerType { span, name, ty } ) ;
9494 } ;
95+ let invalid_monomorphization_int_or_ptr_type = |ty| {
96+ bx. tcx ( ) . dcx ( ) . emit_err ( InvalidMonomorphization :: BasicIntegerOrPtrType {
97+ span,
98+ name,
99+ ty,
100+ } ) ;
101+ } ;
95102
96103 let parse_atomic_ordering = |ord : ty:: Value < ' tcx > | {
97104 let discr = ord. valtree . unwrap_branch ( ) [ 0 ] . unwrap_leaf ( ) ;
@@ -351,7 +358,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
351358 sym:: atomic_load => {
352359 let ty = fn_args. type_at ( 0 ) ;
353360 if !( int_type_width_signed ( ty, bx. tcx ( ) ) . is_some ( ) || ty. is_raw_ptr ( ) ) {
354- invalid_monomorphization_int_type ( ty) ;
361+ invalid_monomorphization_int_or_ptr_type ( ty) ;
355362 return Ok ( ( ) ) ;
356363 }
357364 let ordering = fn_args. const_at ( 1 ) . to_value ( ) ;
@@ -367,7 +374,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
367374 sym:: atomic_store => {
368375 let ty = fn_args. type_at ( 0 ) ;
369376 if !( int_type_width_signed ( ty, bx. tcx ( ) ) . is_some ( ) || ty. is_raw_ptr ( ) ) {
370- invalid_monomorphization_int_type ( ty) ;
377+ invalid_monomorphization_int_or_ptr_type ( ty) ;
371378 return Ok ( ( ) ) ;
372379 }
373380 let ordering = fn_args. const_at ( 1 ) . to_value ( ) ;
@@ -377,10 +384,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
377384 bx. atomic_store ( val, ptr, parse_atomic_ordering ( ordering) , size) ;
378385 return Ok ( ( ) ) ;
379386 }
387+ // These are all AtomicRMW ops
380388 sym:: atomic_cxchg | sym:: atomic_cxchgweak => {
381389 let ty = fn_args. type_at ( 0 ) ;
382390 if !( int_type_width_signed ( ty, bx. tcx ( ) ) . is_some ( ) || ty. is_raw_ptr ( ) ) {
383- invalid_monomorphization_int_type ( ty) ;
391+ invalid_monomorphization_int_or_ptr_type ( ty) ;
384392 return Ok ( ( ) ) ;
385393 }
386394 let succ_ordering = fn_args. const_at ( 1 ) . to_value ( ) ;
@@ -407,7 +415,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
407415
408416 return Ok ( ( ) ) ;
409417 }
410- // These are all AtomicRMW ops
411418 sym:: atomic_max | sym:: atomic_min => {
412419 let atom_op = if name == sym:: atomic_max {
413420 AtomicRmwBinOp :: AtomicMax
@@ -420,7 +427,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
420427 let ordering = fn_args. const_at ( 1 ) . to_value ( ) ;
421428 let ptr = args[ 0 ] . immediate ( ) ;
422429 let val = args[ 1 ] . immediate ( ) ;
423- bx. atomic_rmw ( atom_op, ptr, val, parse_atomic_ordering ( ordering) )
430+ bx. atomic_rmw (
431+ atom_op,
432+ ptr,
433+ val,
434+ parse_atomic_ordering ( ordering) ,
435+ /* ret_ptr */ false ,
436+ )
424437 } else {
425438 invalid_monomorphization_int_type ( ty) ;
426439 return Ok ( ( ) ) ;
@@ -438,21 +451,44 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
438451 let ordering = fn_args. const_at ( 1 ) . to_value ( ) ;
439452 let ptr = args[ 0 ] . immediate ( ) ;
440453 let val = args[ 1 ] . immediate ( ) ;
441- bx. atomic_rmw ( atom_op, ptr, val, parse_atomic_ordering ( ordering) )
454+ bx. atomic_rmw (
455+ atom_op,
456+ ptr,
457+ val,
458+ parse_atomic_ordering ( ordering) ,
459+ /* ret_ptr */ false ,
460+ )
442461 } else {
443462 invalid_monomorphization_int_type ( ty) ;
444463 return Ok ( ( ) ) ;
445464 }
446465 }
447- sym:: atomic_xchg
448- | sym:: atomic_xadd
466+ sym:: atomic_xchg => {
467+ let ty = fn_args. type_at ( 0 ) ;
468+ let ordering = fn_args. const_at ( fn_args. len ( ) - 1 ) . to_value ( ) ;
469+ let ptr = args[ 0 ] . immediate ( ) ;
470+ let val = args[ 1 ] . immediate ( ) ;
471+ if int_type_width_signed ( ty, bx. tcx ( ) ) . is_some ( ) || ty. is_raw_ptr ( ) {
472+ let atomic_op = AtomicRmwBinOp :: AtomicXchg ;
473+ bx. atomic_rmw (
474+ atomic_op,
475+ ptr,
476+ val,
477+ parse_atomic_ordering ( ordering) ,
478+ /* ret_ptr */ ty. is_raw_ptr ( ) ,
479+ )
480+ } else {
481+ invalid_monomorphization_int_or_ptr_type ( ty) ;
482+ return Ok ( ( ) ) ;
483+ }
484+ }
485+ sym:: atomic_xadd
449486 | sym:: atomic_xsub
450487 | sym:: atomic_and
451488 | sym:: atomic_nand
452489 | sym:: atomic_or
453490 | sym:: atomic_xor => {
454491 let atom_op = match name {
455- sym:: atomic_xchg => AtomicRmwBinOp :: AtomicXchg ,
456492 sym:: atomic_xadd => AtomicRmwBinOp :: AtomicAdd ,
457493 sym:: atomic_xsub => AtomicRmwBinOp :: AtomicSub ,
458494 sym:: atomic_and => AtomicRmwBinOp :: AtomicAnd ,
@@ -462,14 +498,28 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
462498 _ => unreachable ! ( ) ,
463499 } ;
464500
465- let ty = fn_args. type_at ( 0 ) ;
466- if int_type_width_signed ( ty, bx. tcx ( ) ) . is_some ( ) || ty. is_raw_ptr ( ) {
467- let ordering = fn_args. const_at ( 1 ) . to_value ( ) ;
468- let ptr = args[ 0 ] . immediate ( ) ;
469- let val = args[ 1 ] . immediate ( ) ;
470- bx. atomic_rmw ( atom_op, ptr, val, parse_atomic_ordering ( ordering) )
501+ // The type of the in-memory data.
502+ let ty_mem = fn_args. type_at ( 0 ) ;
503+ // The type of the 2nd operand, given by-value.
504+ let ty_op = fn_args. type_at ( 1 ) ;
505+
506+ let ordering = fn_args. const_at ( 2 ) . to_value ( ) ;
507+ let ptr = args[ 0 ] . immediate ( ) ; // of type "pointer to `ty_mem`"
508+ let val = args[ 1 ] . immediate ( ) ; // of type `ty_op`
509+ // We require either both arguments to have the same integer type, or the first to
510+ // be a pointer and the second to be `usize`.
511+ if ( int_type_width_signed ( ty_mem, bx. tcx ( ) ) . is_some ( ) && ty_op == ty_mem)
512+ || ( ty_mem. is_raw_ptr ( ) && ty_op == bx. tcx ( ) . types . usize )
513+ {
514+ bx. atomic_rmw (
515+ atom_op,
516+ ptr,
517+ val,
518+ parse_atomic_ordering ( ordering) ,
519+ /* ret_ptr */ ty_mem. is_raw_ptr ( ) ,
520+ )
471521 } else {
472- invalid_monomorphization_int_type ( ty ) ;
522+ invalid_monomorphization_int_or_ptr_type ( ty_mem ) ;
473523 return Ok ( ( ) ) ;
474524 }
475525 }
0 commit comments