Skip to content

Commit 683631a

Browse files
authored
Rollup merge of rust-lang#97423 - m-ou-se:memory-ordering-intrinsics, r=tmiasko
Simplify memory ordering intrinsics This changes the names of the atomic intrinsics to always fully include their memory ordering arguments. ```diff - atomic_cxchg + atomic_cxchg_seqcst_seqcst - atomic_cxchg_acqrel + atomic_cxchg_acqrel_release - atomic_cxchg_acqrel_failrelaxed + atomic_cxchg_acqrel_relaxed // And so on. ``` - `seqcst` is no longer implied - The failure ordering on chxchg is no longer implied in some cases, but now always explicitly part of the name. - `release` is no longer shortened to just `rel`. That was especially confusing, since `relaxed` also starts with `rel`. - `acquire` is no longer shortened to just `acq`, such that the names now all match the `std::sync::atomic::Ordering` variants exactly. - This now allows for more combinations on the compare exchange operations, such as `atomic_cxchg_acquire_release`, which is necessary for rust-lang#68464. - This PR only exposes the new possibilities through unstable intrinsics, but not yet through the stable API. That's for [a separate PR](rust-lang#98383) that requires an FCP. Suffixes for operations with a single memory order: | Order | Before | After | |---------|--------------|------------| | Relaxed | `_relaxed` | `_relaxed` | | Acquire | `_acq` | `_acquire` | | Release | `_rel` | `_release` | | AcqRel | `_acqrel` | `_acqrel` | | SeqCst | (none) | `_seqcst` | Suffixes for compare-and-exchange operations with two memory orderings: | Success | Failure | Before | After | |---------|---------|--------------------------|--------------------| | Relaxed | Relaxed | `_relaxed` | `_relaxed_relaxed` | | Relaxed | Acquire | ❌ | `_relaxed_acquire` | | Relaxed | SeqCst | ❌ | `_relaxed_seqcst` | | Acquire | Relaxed | `_acq_failrelaxed` | `_acquire_relaxed` | | Acquire | Acquire | `_acq` | `_acquire_acquire` | | Acquire | SeqCst | ❌ | `_acquire_seqcst` | | Release | Relaxed | `_rel` | `_release_relaxed` | | Release | Acquire | ❌ | `_release_acquire` | | Release | SeqCst | ❌ | `_release_seqcst` | | AcqRel | Relaxed | `_acqrel_failrelaxed` | `_acqrel_relaxed` | | AcqRel | Acquire | `_acqrel` | `_acqrel_acquire` | | AcqRel | SeqCst | ❌ | `_acqrel_seqcst` | | SeqCst | Relaxed | `_failrelaxed` | `_seqcst_relaxed` | | SeqCst | Acquire | `_failacq` | `_seqcst_acquire` | | SeqCst | SeqCst | (none) | `_seqcst_seqcst` |
2 parents 0399909 + 2d02416 commit 683631a

File tree

11 files changed

+693
-375
lines changed

11 files changed

+693
-375
lines changed

compiler/rustc_codegen_ssa/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#![feature(associated_type_bounds)]
77
#![feature(strict_provenance)]
88
#![feature(int_roundings)]
9+
#![feature(if_let_guard)]
910
#![recursion_limit = "256"]
1011
#![allow(rustc::potential_query_instability)]
1112

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

+26-32
Original file line numberDiff line numberDiff line change
@@ -376,32 +376,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
376376
}
377377

378378
// This requires that atomic intrinsics follow a specific naming pattern:
379-
// "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
380-
name if name_str.starts_with("atomic_") => {
379+
// "atomic_<operation>[_<ordering>]"
380+
name if let Some(atomic) = name_str.strip_prefix("atomic_") => {
381381
use crate::common::AtomicOrdering::*;
382382
use crate::common::{AtomicRmwBinOp, SynchronizationScope};
383383

384-
let split: Vec<_> = name_str.split('_').collect();
385-
386-
let is_cxchg = split[1] == "cxchg" || split[1] == "cxchgweak";
387-
let (order, failorder) = match split.len() {
388-
2 => (SequentiallyConsistent, SequentiallyConsistent),
389-
3 => match split[2] {
390-
"unordered" => (Unordered, Unordered),
391-
"relaxed" => (Relaxed, Relaxed),
392-
"acq" => (Acquire, Acquire),
393-
"rel" => (Release, Relaxed),
394-
"acqrel" => (AcquireRelease, Acquire),
395-
"failrelaxed" if is_cxchg => (SequentiallyConsistent, Relaxed),
396-
"failacq" if is_cxchg => (SequentiallyConsistent, Acquire),
397-
_ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
398-
},
399-
4 => match (split[2], split[3]) {
400-
("acq", "failrelaxed") if is_cxchg => (Acquire, Relaxed),
401-
("acqrel", "failrelaxed") if is_cxchg => (AcquireRelease, Relaxed),
402-
_ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
403-
},
404-
_ => bx.sess().fatal("Atomic intrinsic not in correct format"),
384+
let Some((instruction, ordering)) = atomic.split_once('_') else {
385+
bx.sess().fatal("Atomic intrinsic missing memory ordering");
386+
};
387+
388+
let parse_ordering = |bx: &Bx, s| match s {
389+
"unordered" => Unordered,
390+
"relaxed" => Relaxed,
391+
"acquire" => Acquire,
392+
"release" => Release,
393+
"acqrel" => AcquireRelease,
394+
"seqcst" => SequentiallyConsistent,
395+
_ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
405396
};
406397

407398
let invalid_monomorphization = |ty| {
@@ -416,11 +407,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
416407
);
417408
};
418409

419-
match split[1] {
410+
match instruction {
420411
"cxchg" | "cxchgweak" => {
412+
let Some((success, failure)) = ordering.split_once('_') else {
413+
bx.sess().fatal("Atomic compare-exchange intrinsic missing failure memory ordering");
414+
};
421415
let ty = substs.type_at(0);
422416
if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
423-
let weak = split[1] == "cxchgweak";
417+
let weak = instruction == "cxchgweak";
424418
let mut dst = args[0].immediate();
425419
let mut cmp = args[1].immediate();
426420
let mut src = args[2].immediate();
@@ -432,7 +426,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
432426
cmp = bx.ptrtoint(cmp, bx.type_isize());
433427
src = bx.ptrtoint(src, bx.type_isize());
434428
}
435-
let pair = bx.atomic_cmpxchg(dst, cmp, src, order, failorder, weak);
429+
let pair = bx.atomic_cmpxchg(dst, cmp, src, parse_ordering(bx, success), parse_ordering(bx, failure), weak);
436430
let val = bx.extract_value(pair, 0);
437431
let success = bx.extract_value(pair, 1);
438432
let val = bx.from_immediate(val);
@@ -460,11 +454,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
460454
let llty = bx.type_isize();
461455
let ptr_llty = bx.type_ptr_to(llty);
462456
source = bx.pointercast(source, ptr_llty);
463-
let result = bx.atomic_load(llty, source, order, size);
457+
let result = bx.atomic_load(llty, source, parse_ordering(bx, ordering), size);
464458
// ... and then cast the result back to a pointer
465459
bx.inttoptr(result, bx.backend_type(layout))
466460
} else {
467-
bx.atomic_load(bx.backend_type(layout), source, order, size)
461+
bx.atomic_load(bx.backend_type(layout), source, parse_ordering(bx, ordering), size)
468462
}
469463
} else {
470464
return invalid_monomorphization(ty);
@@ -484,20 +478,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
484478
ptr = bx.pointercast(ptr, ptr_llty);
485479
val = bx.ptrtoint(val, bx.type_isize());
486480
}
487-
bx.atomic_store(val, ptr, order, size);
481+
bx.atomic_store(val, ptr, parse_ordering(bx, ordering), size);
488482
return;
489483
} else {
490484
return invalid_monomorphization(ty);
491485
}
492486
}
493487

494488
"fence" => {
495-
bx.atomic_fence(order, SynchronizationScope::CrossThread);
489+
bx.atomic_fence(parse_ordering(bx, ordering), SynchronizationScope::CrossThread);
496490
return;
497491
}
498492

499493
"singlethreadfence" => {
500-
bx.atomic_fence(order, SynchronizationScope::SingleThread);
494+
bx.atomic_fence(parse_ordering(bx, ordering), SynchronizationScope::SingleThread);
501495
return;
502496
}
503497

@@ -531,7 +525,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
531525
ptr = bx.pointercast(ptr, ptr_llty);
532526
val = bx.ptrtoint(val, bx.type_isize());
533527
}
534-
bx.atomic_rmw(atom_op, ptr, val, order)
528+
bx.atomic_rmw(atom_op, ptr, val, parse_ordering(bx, ordering))
535529
} else {
536530
return invalid_monomorphization(ty);
537531
}

compiler/rustc_error_codes/src/error_codes/E0093.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ functions are defined in `compiler/rustc_codegen_llvm/src/intrinsic.rs` and in
2424
#![feature(intrinsics)]
2525
2626
extern "rust-intrinsic" {
27-
fn atomic_fence(); // ok!
27+
fn atomic_fence_seqcst(); // ok!
2828
}
2929
3030
fn main() {
3131
unsafe {
32-
atomic_fence();
32+
atomic_fence_seqcst();
3333
}
3434
}
3535
```

0 commit comments

Comments
 (0)