@@ -99,6 +99,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
9999
100100 let llret_ty = bx.backend_type(bx.layout_of(ret_ty));
101101
102+ let ret_llval = |bx: &mut Bx, llval| {
103+ if result.layout.ty.is_bool() {
104+ OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout)
105+ .val
106+ .store(bx, result);
107+ } else if !result.layout.ty.is_unit() {
108+ bx.store_to_place(llval, result.val);
109+ }
110+ Ok(())
111+ };
112+
102113 let llval = match name {
103114 sym::abort => {
104115 bx.abort();
@@ -337,6 +348,53 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
337348 use crate::common::AtomicOrdering::*;
338349 use crate::common::{AtomicRmwBinOp, SynchronizationScope};
339350
351+ let invalid_monomorphization = |ty| {
352+ bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
353+ span,
354+ name,
355+ ty,
356+ });
357+ };
358+
359+ let parse_const_generic_ordering = |ord: ty::Value<'tcx>| {
360+ let discr = ord.valtree.unwrap_branch()[0].unwrap_leaf();
361+ let ord = discr.to_atomic_ordering();
362+ // We have to translate from the intrinsic ordering to the backend ordering.
363+ use rustc_middle::ty::AtomicOrdering;
364+ match ord {
365+ AtomicOrdering::Relaxed => Relaxed,
366+ AtomicOrdering::Release => Release,
367+ AtomicOrdering::Acquire => Acquire,
368+ AtomicOrdering::AcqRel => AcquireRelease,
369+ AtomicOrdering::SeqCst => SequentiallyConsistent,
370+ }
371+ };
372+
373+ // Some intrinsics have the ordering already converted to a const generic parameter, we handle those first.
374+ match name {
375+ sym::atomic_load => {
376+ let ty = fn_args.type_at(0);
377+ let ordering = fn_args.const_at(1).to_value();
378+ if !(int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr()) {
379+ invalid_monomorphization(ty);
380+ return Ok(());
381+ }
382+ let layout = bx.layout_of(ty);
383+ let source = args[0].immediate();
384+ let llval = bx.atomic_load(
385+ bx.backend_type(layout),
386+ source,
387+ parse_const_generic_ordering(ordering),
388+ layout.size,
389+ );
390+
391+ return ret_llval(bx, llval);
392+ }
393+
394+ // The rest falls back to below.
395+ _ => {}
396+ }
397+
340398 let Some((instruction, ordering)) = atomic.split_once('_') else {
341399 bx.sess().dcx().emit_fatal(errors::MissingMemoryOrdering);
342400 };
@@ -350,14 +408,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
350408 _ => bx.sess().dcx().emit_fatal(errors::UnknownAtomicOrdering),
351409 };
352410
353- let invalid_monomorphization = |ty| {
354- bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
355- span,
356- name,
357- ty,
358- });
359- };
360-
361411 match instruction {
362412 "cxchg" | "cxchgweak" => {
363413 let Some((success, failure)) = ordering.split_once('_') else {
@@ -390,24 +440,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
390440 return Ok(());
391441 }
392442
393- "load" => {
394- let ty = fn_args.type_at(0);
395- if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() {
396- let layout = bx.layout_of(ty);
397- let size = layout.size;
398- let source = args[0].immediate();
399- bx.atomic_load(
400- bx.backend_type(layout),
401- source,
402- parse_ordering(bx, ordering),
403- size,
404- )
405- } else {
406- invalid_monomorphization(ty);
407- return Ok(());
408- }
409- }
410-
411443 "store" => {
412444 let ty = fn_args.type_at(0);
413445 if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() {
@@ -538,14 +570,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
538570 }
539571 };
540572
541- if result.layout.ty.is_bool() {
542- OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout)
543- .val
544- .store(bx, result);
545- } else if !result.layout.ty.is_unit() {
546- bx.store_to_place(llval, result.val);
547- }
548- Ok(())
573+ ret_llval(bx, llval)
549574 }
550575}
551576
0 commit comments