From: Yap Zhi Heng <[email protected]>

gcc/rust/ChangeLog:

        * util/rust-intrinsic-values.h (Intrinsics): Add new entries for atomic 
fence
        function names.
        * backend/rust-intrinsic-handlers.h (inner::atomic_fence): New function 
for compiling
        atomic fence intrinsics.
        (atomic_fence): New function to handle atomic_fence and its variants.
        * backend/rust-intrinsic-handlers.cc (inner:atomic_fence): Implement.
        (atomic_fence): Implement.
        * backend/rust-compile-intrinsic.cc (generic_intrinsics): Add entries 
for the new atomic
        fence intrinsics.
        * typecheck/rust-hir-type-check-intrinsic.cc (intrinsic_rules): 
Likewise, but for type
        checking.

gcc/testsuite/ChangeLog:

        * rust/execute/torture/atomic_load.rs: Add an atomic_fence.
        * rust/execute/torture/atomic_store.rs: Likewise.

Signed-off-by: Yap Zhi Heng <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/3a53dbd73d9a77402ec7ba28466e219c1c091067

The commit has NOT been mentioned in any issue.

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4993

 gcc/rust/backend/rust-compile-intrinsic.cc    | 13 +++++++++
 gcc/rust/backend/rust-intrinsic-handlers.cc   | 29 +++++++++++++++++++
 gcc/rust/backend/rust-intrinsic-handlers.h    |  1 +
 .../rust-hir-type-check-intrinsic.cc          |  9 ++++++
 gcc/rust/util/rust-intrinsic-values.h         | 12 ++++++++
 .../rust/execute/torture/atomic_load.rs       |  3 ++
 .../rust/execute/torture/atomic_store.rs      |  3 ++
 7 files changed, 70 insertions(+)

diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc 
b/gcc/rust/backend/rust-compile-intrinsic.cc
index 5ebcec660..994dda03c 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -180,6 +180,19 @@ static const std::map<std::string, Intrinsic::CompileFn> 
intrinsics = {
   {IValue::ATOMIC_UMIN_RELAXED,
    handlers::atomic_minmax (handlers::AtomicMinMaxKind::UnsignedMin,
                            __ATOMIC_RELAXED)},
+  {IValue::ATOMIC_FENCE, handlers::atomic_fence (true, __ATOMIC_SEQ_CST)},
+  {IValue::ATOMIC_FENCE_ACQ, handlers::atomic_fence (true, __ATOMIC_ACQUIRE)},
+  {IValue::ATOMIC_FENCE_REL, handlers::atomic_fence (true, __ATOMIC_RELEASE)},
+  {IValue::ATOMIC_FENCE_ACQREL,
+   handlers::atomic_fence (true, __ATOMIC_ACQ_REL)},
+  {IValue::ATOMIC_SINGLETHREADFENCE,
+   handlers::atomic_fence (false, __ATOMIC_SEQ_CST)},
+  {IValue::ATOMIC_SINGLETHREADFENCE_ACQ,
+   handlers::atomic_fence (false, __ATOMIC_ACQUIRE)},
+  {IValue::ATOMIC_SINGLETHREADFENCE_REL,
+   handlers::atomic_fence (false, __ATOMIC_RELEASE)},
+  {IValue::ATOMIC_SINGLETHREADFENCE_ACQREL,
+   handlers::atomic_fence (false, __ATOMIC_ACQ_REL)},
   {IValue::UNCHECKED_ADD, handlers::unchecked_op (PLUS_EXPR)},
   {IValue::UNCHECKED_SUB, handlers::unchecked_op (MINUS_EXPR)},
   {IValue::UNCHECKED_MUL, handlers::unchecked_op (MULT_EXPR)},
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.cc 
b/gcc/rust/backend/rust-intrinsic-handlers.cc
index 84eb4cbbb..dcaf046a4 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.cc
+++ b/gcc/rust/backend/rust-intrinsic-handlers.cc
@@ -794,6 +794,27 @@ atomic_minmax (IntrinsicCtx &ctx, AtomicMinMaxKind kind, 
int ordering)
     Backend::return_statement (ctx.fn, expected, UNDEF_LOCATION));
 }
 
+static void
+atomic_fence (IntrinsicCtx &ctx, bool is_multithread, int ordering)
+{
+  // Most intrinsic functions are pure but not the atomic ones
+  TREE_READONLY (ctx.fn) = 0;
+  TREE_SIDE_EFFECTS (ctx.fn) = 1;
+
+  auto builtin_decl = BuiltinsContext::get ().lookup_simple_builtin (
+    is_multithread ? "__atomic_thread_fence" : "__atomic_signal_fence");
+  rust_assert (builtin_decl);
+
+  auto fence = build_fold_addr_expr_loc (UNDEF_LOCATION, *builtin_decl);
+  auto memorder = make_unsigned_long_tree (ordering);
+  auto fence_call
+    = Backend::call_expression (fence, {memorder}, nullptr, UNDEF_LOCATION);
+  TREE_READONLY (fence_call) = 0;
+  TREE_SIDE_EFFECTS (fence_call) = 1;
+
+  ctx.add_statement (fence_call);
+}
+
 // Shared inner implementation for ctlz and ctlz_nonzero.
 //
 // nonzero=false → ctlz: ctlz(0) is well-defined in Rust and must return
@@ -1291,6 +1312,14 @@ atomic_minmax (AtomicMinMaxKind kind, int ordering)
   };
 }
 
+Intrinsic::CompileFn
+atomic_fence (bool is_multithread, int ordering)
+{
+  return [is_multithread, ordering] (IntrinsicCtx &ctx) {
+    return inner::atomic_fence (ctx, is_multithread, ordering);
+  };
+}
+
 Intrinsic::CompileFn
 unchecked_op (tree_code op)
 {
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.h 
b/gcc/rust/backend/rust-intrinsic-handlers.h
index 685612b2f..8d5cb9f73 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.h
+++ b/gcc/rust/backend/rust-intrinsic-handlers.h
@@ -214,6 +214,7 @@ Intrinsic::CompileFn atomic_compare_exchange (bool weak, 
int success_ordering,
                                              int failure_ordering);
 Intrinsic::CompileFn atomic_minmax (handlers::AtomicMinMaxKind kind,
                                    int ordering);
+Intrinsic::CompileFn atomic_fence (bool is_multithread, int ordering);
 
 Intrinsic::CompileFn unchecked_op (tree_code op);
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc 
b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
index 8a632fae8..c423cbb43 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
@@ -359,6 +359,15 @@ const std::unordered_map<std::string, IntrinsicRules>
      {1,
       {IRT::MutPtrFirstGeneric, IRT::FirstGeneric, IRT::FirstGeneric},
       IRT::TupleFirstGenericAndBool}},
+    // pub fn atomic_fence*/atomic_singlethreadfence*();
+    {IValue::ATOMIC_FENCE, {0, {}, IRT::Unit}},
+    {IValue::ATOMIC_FENCE_ACQ, {0, {}, IRT::Unit}},
+    {IValue::ATOMIC_FENCE_REL, {0, {}, IRT::Unit}},
+    {IValue::ATOMIC_FENCE_ACQREL, {0, {}, IRT::Unit}},
+    {IValue::ATOMIC_SINGLETHREADFENCE, {0, {}, IRT::Unit}},
+    {IValue::ATOMIC_SINGLETHREADFENCE_ACQ, {0, {}, IRT::Unit}},
+    {IValue::ATOMIC_SINGLETHREADFENCE_REL, {0, {}, IRT::Unit}},
+    {IValue::ATOMIC_SINGLETHREADFENCE_ACQREL, {0, {}, IRT::Unit}},
     // pub fn unchecked_add<T: Copy>(x: T, y: T) -> T;
     {IValue::UNCHECKED_ADD,
      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
diff --git a/gcc/rust/util/rust-intrinsic-values.h 
b/gcc/rust/util/rust-intrinsic-values.h
index 37f61f8cb..2560739b8 100644
--- a/gcc/rust/util/rust-intrinsic-values.h
+++ b/gcc/rust/util/rust-intrinsic-values.h
@@ -196,6 +196,18 @@ public:
   static constexpr auto &ATOMIC_CXCHGWEAK_ACQREL_FAILRELAXED
     = "atomic_cxchgweak_acqrel_failrelaxed";
 
+  static constexpr auto &ATOMIC_FENCE = "atomic_fence";
+  static constexpr auto &ATOMIC_FENCE_ACQ = "atomic_fence_acq";
+  static constexpr auto &ATOMIC_FENCE_REL = "atomic_fence_rel";
+  static constexpr auto &ATOMIC_FENCE_ACQREL = "atomic_fence_acqrel";
+  static constexpr auto &ATOMIC_SINGLETHREADFENCE = "atomic_singlethreadfence";
+  static constexpr auto &ATOMIC_SINGLETHREADFENCE_ACQ
+    = "atomic_singlethreadfence_acq";
+  static constexpr auto &ATOMIC_SINGLETHREADFENCE_REL
+    = "atomic_singlethreadfence_rel";
+  static constexpr auto &ATOMIC_SINGLETHREADFENCE_ACQREL
+    = "atomic_singlethreadfence_acqrel";
+
   static constexpr auto &UNCHECKED_ADD = "unchecked_add";
   static constexpr auto &UNCHECKED_SUB = "unchecked_sub";
   static constexpr auto &UNCHECKED_MUL = "unchecked_mul";
diff --git a/gcc/testsuite/rust/execute/torture/atomic_load.rs 
b/gcc/testsuite/rust/execute/torture/atomic_load.rs
index bddfff563..d967911fc 100644
--- a/gcc/testsuite/rust/execute/torture/atomic_load.rs
+++ b/gcc/testsuite/rust/execute/torture/atomic_load.rs
@@ -68,6 +68,7 @@ extern "rust-intrinsic" {
     pub fn atomic_load_acquire<T: Copy>(src: *const T) -> T;
     pub fn atomic_load_relaxed<T: Copy>(src: *const T) -> T;
     pub fn atomic_load_unordered<T: Copy>(src: *const T) -> T;
+    pub fn atomic_fence();
 }
 
 fn main() -> u32 {
@@ -88,6 +89,8 @@ fn main() -> u32 {
 
         src = 4;
         four = atomic_load_unordered(&src);
+
+        atomic_fence();
     }
 
     (four + three + two + one) - 10
diff --git a/gcc/testsuite/rust/execute/torture/atomic_store.rs 
b/gcc/testsuite/rust/execute/torture/atomic_store.rs
index e6602a75b..cc6d3e5bf 100644
--- a/gcc/testsuite/rust/execute/torture/atomic_store.rs
+++ b/gcc/testsuite/rust/execute/torture/atomic_store.rs
@@ -68,6 +68,7 @@ extern "rust-intrinsic" {
     pub fn atomic_store_release<T: Copy>(dst: *mut T, val: T);
     pub fn atomic_store_relaxed<T: Copy>(dst: *mut T, val: T);
     pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T);
+    pub fn atomic_fence();
 }
 
 fn main() -> u32 {
@@ -89,6 +90,8 @@ fn main() -> u32 {
 
         atomic_store_unordered(&mut dst, 4);
         four = dst;
+
+        atomic_fence();
     }
 
     (four + three + two + one) - 10
-- 
2.56.0

Reply via email to