[gcc r17-2246] gccrs: intrinsic: Add write_bytes

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

commit r17-2246-g64f2b1110994bc506ad2b88932a7089c8438b6b3
Author: Enes Cevik <[email protected]>
Date:   Fri Jun 26 15:53:46 2026 +0300

    gccrs: intrinsic: Add write_bytes
    
    This patch implements the 'write_bytes' compiler intrinsic. It performs
    a write operation to memory using '__builtin_memset'.
    
    gcc/rust/ChangeLog:
    
            * backend/rust-compile-intrinsic.cc (generic_intrinsics): Add
            write_bytes handler to map.
            * backend/rust-intrinsic-handlers.cc (write_bytes_handler): New
            function.
            * backend/rust-intrinsic-handlers.h (write_bytes_handler): New
            declaration.
            * typecheck/rust-hir-type-check-intrinsic.cc
            (IntrinsicChecker::intrinsic_rules): Add write_bytes rule.
            * util/rust-intrinsic-values.h (class Intrinsics): Add
            WRITE_BYTES constexpr.
    
    gcc/testsuite/ChangeLog:
    
            * rust/execute/write-bytes.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        | 70 ++++++++++++++++++++++
 gcc/rust/backend/rust-intrinsic-handlers.h         |  3 +
 .../typecheck/rust-hir-type-check-intrinsic.cc     |  5 ++
 gcc/rust/util/rust-intrinsic-values.h              |  1 +
 gcc/testsuite/rust/execute/write-bytes.rs          | 17 ++++++
 6 files changed, 97 insertions(+)

diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index a00b2a50ef07..51531de3c65e 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::WRITE_BYTES, handlers::write_bytes_handler},
      {IValue::SIZE_OF, handlers::sizeof_handler},
      {IValue::MIN_ALIGN_OF, handlers::min_align_of_handler},
      {IValue::TRANSMUTE, handlers::transmute},
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.cc b/gcc/rust/backend/rust-intrinsic-handlers.cc
index 8ea93d7f781c..24f831ec7ae6 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.cc
+++ b/gcc/rust/backend/rust-intrinsic-handlers.cc
@@ -1865,6 +1865,76 @@ cttz_nonzero_handler (Context *ctx, TyTy::FnType *fntype, location_t)
   return inner::cttz_handler (ctx, fntype, true);
 }
 
+/**
+ * pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
+ */
+tree
+write_bytes_handler (Context *ctx, TyTy::FnType *fntype, location_t)
+{
+  rust_assert (fntype->get_params ().size () == 3);
+
+  tree lookup = NULL_TREE;
+  if (check_for_cached_intrinsic (ctx, fntype, &lookup))
+    return lookup;
+
+  tree 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 &val_param = param_vars.at (1);
+  auto &count_param = param_vars.at (2);
+  rust_assert (param_vars.size () == 3);
+  if (!Backend::function_set_parameters (fndecl, param_vars))
+    return error_mark_node;
+
+  auto *monomorphized_type
+    = fntype->get_substs ().at (0).get_param_ty ()->resolve ();
+
+  tree template_parameter_type
+    = TyTyResolveCompile::compile (ctx, monomorphized_type);
+  tree dst_size_expr = TYPE_SIZE_UNIT (template_parameter_type);
+  rust_assert (dst_size_expr != NULL_TREE);
+
+  enter_intrinsic_block (ctx, fndecl);
+
+  // BUILTIN WRITE_BYTES FN BODY START
+
+  tree expr_dst = Backend::var_expression (dst_param, locus);
+  tree expr_val = Backend::var_expression (val_param, locus);
+  tree expr_count = Backend::var_expression (count_param, locus);
+
+  tree expr_count_final
+    = fold_build2_loc (locus, MULT_EXPR, size_type_node,
+		       fold_convert_loc (locus, size_type_node, expr_count),
+		       fold_convert_loc (locus, size_type_node, dst_size_expr));
+
+  tree write_bytes_raw = nullptr;
+  // void* memset( void* dest, int ch, size_t count );
+  bool ok = BuiltinsContext::get ().lookup_simple_builtin ("__builtin_memset",
+							   &write_bytes_raw);
+  rust_assert (ok);
+
+  tree write_bytes_fn = build_fold_addr_expr_loc (locus, write_bytes_raw);
+  tree write_bytes_call
+    = Backend::call_expression (write_bytes_fn,
+				{expr_dst, expr_val, expr_count_final},
+				NULL_TREE, locus);
+
+  ctx->add_statement (write_bytes_call);
+
+  // BUILTIN WRITE_BYTES FN BODY END
+
+  finalize_intrinsic_block (ctx, fndecl);
+
+  TREE_READONLY (fndecl) = 0;
+
+  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 34e9f49d73b4..c088f9ff4d85 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.h
+++ b/gcc/rust/backend/rust-intrinsic-handlers.h
@@ -96,6 +96,9 @@ tree prefetch_write_data (Context *ctx, TyTy::FnType *fntype,
 			  location_t expr_locus);
 tree sorry (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
 
+tree write_bytes_handler (Context *ctx, TyTy::FnType *fntype,
+			  location_t expr_locus);
+
 } // namespace handlers
 
 } // namespace Compile
diff --git a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
index 8f51cf135c80..af27a2ddb982 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
@@ -300,6 +300,11 @@ const std::unordered_map<std::string, IntrinsicRules>
     {IValue::FORGET, {1, {IRT::FirstGeneric}, IRT::Unit}},
     // pub fn black_box<T>(mut dummy: T) -> T
     {IValue::BLACK_BOX, {1, {IRT::FirstGeneric}, IRT::FirstGeneric}},
+
+    // fn write_bytes<T>(dst: *mut T, val: u8, count: usize)
+    {IValue::WRITE_BYTES,
+     {1, {IRT::MutPtrFirstGeneric, IRT::U8, IRT::Usize}, IRT::Unit}},
+
 };
 
 IntrinsicCheckResult
diff --git a/gcc/rust/util/rust-intrinsic-values.h b/gcc/rust/util/rust-intrinsic-values.h
index 1c275e7b74e6..10c5c1eb2b00 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 &WRITE_BYTES = "write_bytes";
 };
 } // namespace Values
 } // namespace Rust
diff --git a/gcc/testsuite/rust/execute/write-bytes.rs b/gcc/testsuite/rust/execute/write-bytes.rs
new file mode 100644
index 000000000000..bc8fd8f46674
--- /dev/null
+++ b/gcc/testsuite/rust/execute/write-bytes.rs
@@ -0,0 +1,17 @@
+#![feature(no_core, intrinsics, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+extern "rust-intrinsic" {
+    fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
+}
+
+fn main() -> i32 {
+    let mut x: u32 = 0;
+    unsafe { 
+        write_bytes(&mut x as *mut u32, 0xEC_u8, 1); 
+    }
+    if x == 0xECECECEC_u32 { 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.