[gcc r17-2247] gccrs: intrinsic: Add arith_offset

Arthur Cohen via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:574afa290276ce7bd67e905613d7b77f066b4a87

commit r17-2247-g574afa290276ce7bd67e905613d7b77f066b4a87
Author: Enes Cevik <[email protected]>
Date:   Fri Jun 26 16:40:51 2026 +0300

    gccrs: intrinsic: Add arith_offset
    
    This patch implements the 'arith_offset' compiler intrinsic. It moves a
    pointer forward or backward by a given number of elements. It does not
    cause Undefined Behavior if the pointer goes out of bounds.
    
    gcc/rust/ChangeLog:
    
            * backend/rust-compile-intrinsic.cc (generic_intrinsics): Add
            arith_offset handler to map.
            * backend/rust-intrinsic-handlers.cc (arith_offset_handler): New
            function.
            * backend/rust-intrinsic-handlers.h (arith_offset_handler): New
            declaration.
            * typecheck/rust-hir-type-check-intrinsic.cc
            (IntrinsicChecker::intrinsic_rules): Add arith_offset rule.
            * util/rust-intrinsic-values.h (class Intrinsics): Add
            ARITH_OFFSET constexpr.
    
    gcc/testsuite/ChangeLog:
    
            * rust/execute/arith-offset.rs: New test.
    
    Signed-off-by: Enes Cevik <[email protected]>

Diff:
---
 gcc/rust/backend/rust-compile-intrinsic.cc         |  1 +
 gcc/rust/backend/rust-intrinsic-handlers.cc        | 39 ++++++++++++++++++++++
 gcc/rust/backend/rust-intrinsic-handlers.h         |  2 ++
 .../typecheck/rust-hir-type-check-intrinsic.cc     |  3 ++
 gcc/rust/util/rust-intrinsic-values.h              |  1 +
 gcc/testsuite/rust/execute/arith-offset.rs         | 23 +++++++++++++
 6 files changed, 69 insertions(+)

diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index 51531de3c65e..e9407e051115 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -29,6 +29,7 @@ using IValue = Values::Intrinsics;
 
 static const std::map<std::string, handlers::HandlerBuilder> generic_intrinsics
   = {{IValue::OFFSET, handlers::offset},
+     {IValue::ARITH_OFFSET, handlers::arith_offset_handler},
      {IValue::WRITE_BYTES, handlers::write_bytes_handler},
      {IValue::SIZE_OF, handlers::sizeof_handler},
      {IValue::MIN_ALIGN_OF, handlers::min_align_of_handler},
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.cc b/gcc/rust/backend/rust-intrinsic-handlers.cc
index 24f831ec7ae6..735529cc947a 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.cc
+++ b/gcc/rust/backend/rust-intrinsic-handlers.cc
@@ -1935,6 +1935,45 @@ write_bytes_handler (Context *ctx, TyTy::FnType *fntype, location_t)
   return fndecl;
 }
 
+/**
+ * pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
+ */
+tree
+arith_offset_handler (Context *ctx, TyTy::FnType *fntype, location_t expr_locus)
+{
+  rust_assert (fntype->get_params ().size () == 2);
+
+  auto fndecl = compile_intrinsic_function (ctx, fntype);
+
+  auto locus = fntype->get_locus ();
+
+  std::vector<Bvariable *> param_vars;
+  compile_fn_params (ctx, fntype, fndecl, &param_vars);
+
+  auto &dst_param = param_vars.at (0);
+  auto &size_param = param_vars.at (1);
+  rust_assert (param_vars.size () == 2);
+  if (!Backend::function_set_parameters (fndecl, param_vars))
+    return error_mark_node;
+
+  enter_intrinsic_block (ctx, fndecl);
+
+  // BUILTIN arith_offset FN BODY BEGIN
+
+  tree dst = Backend::var_expression (dst_param, locus);
+  tree size = Backend::var_expression (size_param, locus);
+  tree pointer_offset_expr = pointer_offset_expression (dst, size, expr_locus);
+  auto return_statement
+    = Backend::return_statement (fndecl, pointer_offset_expr, locus);
+  ctx->add_statement (return_statement);
+
+  // BUILTIN arith_offset FN BODY END
+
+  finalize_intrinsic_block (ctx, fndecl);
+
+  return fndecl;
+}
+
 } // namespace handlers
 } // namespace Compile
 } // namespace Rust
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.h b/gcc/rust/backend/rust-intrinsic-handlers.h
index c088f9ff4d85..1c81417b7024 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.h
+++ b/gcc/rust/backend/rust-intrinsic-handlers.h
@@ -98,6 +98,8 @@ tree sorry (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
 
 tree write_bytes_handler (Context *ctx, TyTy::FnType *fntype,
 			  location_t expr_locus);
+tree arith_offset_handler (Context *ctx, TyTy::FnType *fntype,
+			   location_t expr_locus);
 
 } // namespace handlers
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
index af27a2ddb982..0011e3203d52 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
@@ -301,6 +301,9 @@ const std::unordered_map<std::string, IntrinsicRules>
     // pub fn black_box<T>(mut dummy: T) -> T
     {IValue::BLACK_BOX, {1, {IRT::FirstGeneric}, IRT::FirstGeneric}},
 
+    // pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
+    {IValue::ARITH_OFFSET,
+     {1, {IRT::ConstPtrFirstGeneric, IRT::Isize}, IRT::ConstPtrFirstGeneric}},
     // fn write_bytes<T>(dst: *mut T, val: u8, count: usize)
     {IValue::WRITE_BYTES,
      {1, {IRT::MutPtrFirstGeneric, IRT::U8, IRT::Usize}, IRT::Unit}},
diff --git a/gcc/rust/util/rust-intrinsic-values.h b/gcc/rust/util/rust-intrinsic-values.h
index 10c5c1eb2b00..d47e66ce6e9f 100644
--- a/gcc/rust/util/rust-intrinsic-values.h
+++ b/gcc/rust/util/rust-intrinsic-values.h
@@ -157,6 +157,7 @@ public:
   static constexpr auto &TYPE_NAME = "type_name";
   static constexpr auto &FORGET = "forget";
   static constexpr auto &BLACK_BOX = "black_box";
+  static constexpr auto &ARITH_OFFSET = "arith_offset";
   static constexpr auto &WRITE_BYTES = "write_bytes";
 };
 } // namespace Values
diff --git a/gcc/testsuite/rust/execute/arith-offset.rs b/gcc/testsuite/rust/execute/arith-offset.rs
new file mode 100644
index 000000000000..2daf1d7bed6d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/arith-offset.rs
@@ -0,0 +1,23 @@
+#![feature(no_core, intrinsics, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+extern "rust-intrinsic" {
+    fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+fn main() -> i32 {
+    let base_addr: usize = 0;
+    let ptr = base_addr as *const u64;
+
+    unsafe {
+        let wrap_ptr = arith_offset(ptr, -1);
+        if wrap_ptr as isize == -8_isize {
+            0 
+        } else {
+            1 
+        }
+    }
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.