@@ -99,6 +99,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
9999 let llret_ty = bx. backend_type ( bx. layout_of ( ret_ty) ) ;
100100 let result = PlaceRef :: new_sized ( llresult, fn_abi. ret . layout ) ;
101101
102+ let ret_llval = |bx : & mut Bx , llval| {
103+ if !fn_abi. ret . is_ignore ( ) {
104+ if let PassMode :: Cast { .. } = & fn_abi. ret . mode {
105+ bx. store_to_place ( llval, result. val ) ;
106+ } else {
107+ OperandRef :: from_immediate_or_packed_pair ( bx, llval, result. layout )
108+ . val
109+ . store ( bx, result) ;
110+ }
111+ }
112+ Ok ( ( ) )
113+ } ;
114+
102115 let llval = match name {
103116 sym:: abort => {
104117 bx. abort ( ) ;
@@ -331,6 +344,53 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
331344 use crate :: common:: AtomicOrdering :: * ;
332345 use crate :: common:: { AtomicRmwBinOp , SynchronizationScope } ;
333346
347+ let invalid_monomorphization = |ty| {
348+ bx. tcx ( ) . dcx ( ) . emit_err ( InvalidMonomorphization :: BasicIntegerType {
349+ span,
350+ name,
351+ ty,
352+ } ) ;
353+ } ;
354+
355+ let parse_const_generic_ordering = |ord : ty:: Value < ' tcx > | {
356+ let discr = ord. valtree . unwrap_branch ( ) [ 0 ] . unwrap_leaf ( ) ;
357+ let ord = discr. to_atomic_ordering ( ) ;
358+ // We have to translate from the intrinsic ordering to the backend ordering.
359+ use std:: intrinsics:: AtomicOrdering ;
360+ match ord {
361+ AtomicOrdering :: Relaxed => Relaxed ,
362+ AtomicOrdering :: Release => Release ,
363+ AtomicOrdering :: Acquire => Acquire ,
364+ AtomicOrdering :: AcqRel => AcquireRelease ,
365+ AtomicOrdering :: SeqCst => SequentiallyConsistent ,
366+ }
367+ } ;
368+
369+ // Some intrinsics have the ordering already converted to a const generic parameter, we handle those first.
370+ match name {
371+ sym:: atomic_load => {
372+ let ty = fn_args. type_at ( 0 ) ;
373+ let ordering = fn_args. const_at ( 1 ) . to_value ( ) ;
374+ if !( int_type_width_signed ( ty, bx. tcx ( ) ) . is_some ( ) || ty. is_raw_ptr ( ) ) {
375+ invalid_monomorphization ( ty) ;
376+ return Ok ( ( ) ) ;
377+ }
378+ let layout = bx. layout_of ( ty) ;
379+ let source = args[ 0 ] . immediate ( ) ;
380+ let llval = bx. atomic_load (
381+ bx. backend_type ( layout) ,
382+ source,
383+ parse_const_generic_ordering ( ordering) ,
384+ layout. size ,
385+ ) ;
386+
387+ return ret_llval ( bx, llval) ;
388+ }
389+
390+ // The rest falls back to below.
391+ _ => { }
392+ }
393+
334394 let Some ( ( instruction, ordering) ) = atomic. split_once ( '_' ) else {
335395 bx. sess ( ) . dcx ( ) . emit_fatal ( errors:: MissingMemoryOrdering ) ;
336396 } ;
@@ -344,14 +404,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
344404 _ => bx. sess ( ) . dcx ( ) . emit_fatal ( errors:: UnknownAtomicOrdering ) ,
345405 } ;
346406
347- let invalid_monomorphization = |ty| {
348- bx. tcx ( ) . dcx ( ) . emit_err ( InvalidMonomorphization :: BasicIntegerType {
349- span,
350- name,
351- ty,
352- } ) ;
353- } ;
354-
355407 match instruction {
356408 "cxchg" | "cxchgweak" => {
357409 let Some ( ( success, failure) ) = ordering. split_once ( '_' ) else {
@@ -384,24 +436,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
384436 return Ok ( ( ) ) ;
385437 }
386438
387- "load" => {
388- let ty = fn_args. type_at ( 0 ) ;
389- if int_type_width_signed ( ty, bx. tcx ( ) ) . is_some ( ) || ty. is_raw_ptr ( ) {
390- let layout = bx. layout_of ( ty) ;
391- let size = layout. size ;
392- let source = args[ 0 ] . immediate ( ) ;
393- bx. atomic_load (
394- bx. backend_type ( layout) ,
395- source,
396- parse_ordering ( bx, ordering) ,
397- size,
398- )
399- } else {
400- invalid_monomorphization ( ty) ;
401- return Ok ( ( ) ) ;
402- }
403- }
404-
405439 "store" => {
406440 let ty = fn_args. type_at ( 0 ) ;
407441 if int_type_width_signed ( ty, bx. tcx ( ) ) . is_some ( ) || ty. is_raw_ptr ( ) {
@@ -532,16 +566,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
532566 }
533567 } ;
534568
535- if !fn_abi. ret . is_ignore ( ) {
536- if let PassMode :: Cast { .. } = & fn_abi. ret . mode {
537- bx. store_to_place ( llval, result. val ) ;
538- } else {
539- OperandRef :: from_immediate_or_packed_pair ( bx, llval, result. layout )
540- . val
541- . store ( bx, result) ;
542- }
543- }
544- Ok ( ( ) )
569+ ret_llval ( bx, llval)
545570 }
546571}
547572
0 commit comments