[gcc r17-3098] gccrs: intrinsic: Add assert_zero_valid

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

commit r17-3098-g44ee83bcf7f1a80d4be275932b771b1f7403863e
Author: Enes Cevik <[email protected]>
Date:   Fri Jul 10 15:39:28 2026 +0300

    gccrs: intrinsic: Add assert_zero_valid
    
    This patch adds the 'assert_zero_valid' intrinsic to the compiler.
    Properly implementing this intrinsic requires layout engine support to
    detect types that cannot be safely zero-initialized (e.g., references
    and NonNull types). Since gccrs currently lacks this capability, it is
    implemented as a temporary stub that always returns unit `()`.
    
    Normally, this intrinsic should inject a runtime panic during codegen
    if the provided type does not permit zero-initialization.
    
    gcc/rust/ChangeLog:
    
            * backend/rust-compile-intrinsic.cc (generic_intrinsics): Add
            assert_zero_valid to map.
            * backend/rust-intrinsic-handlers.cc
            (assert_zero_valid_handler): New function.
            * backend/rust-intrinsic-handlers.h (assert_zero_valid_handler):
            New declaration.
            * typecheck/rust-hir-type-check-intrinsic.cc
            (IntrinsicChecker::intrinsic_rules): Add new signature rule for
            assert_zero_valid.
            * util/rust-intrinsic-values.h (class Intrinsics): Add
            ASSERT_ZERO_VALID constexpr.
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/assert_zero_valid.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        | 51 ++++++++++++++++++++++
 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/compile/assert_zero_valid.rs    | 16 +++++++
 6 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index 205bf4113962..b48647670089 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -31,6 +31,7 @@ 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::ASSERT_ZERO_VALID, handlers::assert_zero_valid_handler},
      {IValue::SIZE_OF, handlers::sizeof_handler},
      {IValue::SIZE_OF_VAL, handlers::size_of_val_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 b119593b8a92..6069898da74e 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.cc
+++ b/gcc/rust/backend/rust-intrinsic-handlers.cc
@@ -2176,6 +2176,57 @@ arith_offset_handler (Context *ctx, TyTy::FnType *fntype, location_t expr_locus)
   return fndecl;
 }
 
+/**
+ * pub fn assert_zero_valid<T>();
+ *
+ * TODO: Since gccrs currently lacks comprehensive layout engine support for
+ * validity ranges (such as `rustc_layout_scalar_valid_range_start`), we cannot
+ * accurately determine if a type is safely zeroable. Therefore, this is
+ * implemented as a temporary no-op stub that always returns void (unit) and
+ * succeeds for all types.
+ */
+tree
+assert_zero_valid_handler (Context *ctx, TyTy::FnType *fntype, location_t)
+{
+  rust_assert (fntype->get_params ().size () == 0);
+
+  tree lookup = NULL_TREE;
+  if (check_for_cached_intrinsic (ctx, fntype, &lookup))
+    return lookup;
+
+  auto fndecl = compile_intrinsic_function (ctx, fntype);
+
+  rust_assert (fntype->get_num_substitutions () == 1);
+  auto &param_mapping = fntype->get_substs ().at (0);
+  const auto param_tyty = param_mapping.get_param_ty ();
+  auto resolved_tyty = param_tyty->resolve ();
+
+  // Safely resolve the template parameter type to ensure monomorphization
+  // works.
+  // Suppress unused-variable warning since layout verification is a FIXME.
+  [[gnu::unused]] tree template_parameter_type
+    = TyTyResolveCompile::compile (ctx, resolved_tyty);
+
+  enter_intrinsic_block (ctx, fndecl);
+
+  // BUILTIN assert_zero_valid FN BODY BEGIN
+
+  // TODO: Implement layout verification via template_parameter_type once
+  // niche-filling and valid scalar ranges are supported in the layout engine.
+  // If invalid, this should emit a panic.
+
+  // we always return unit for now.
+  auto return_statement
+    = Backend::return_statement (fndecl, void_node, UNDEF_LOCATION);
+  ctx->add_statement (return_statement);
+
+  // BUILTIN assert_zero_valid 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 8916c59f39c1..712d422e5148 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.h
+++ b/gcc/rust/backend/rust-intrinsic-handlers.h
@@ -104,6 +104,8 @@ 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);
+tree assert_zero_valid_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 df596c58a4e4..a0a0479639eb 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
@@ -311,7 +311,8 @@ const std::unordered_map<std::string, IntrinsicRules>
     // fn write_bytes<T>(dst: *mut T, val: u8, count: usize)
     {IValue::WRITE_BYTES,
      {1, {IRT::MutPtrFirstGeneric, IRT::U8, IRT::Usize}, IRT::Unit}},
-
+    // pub fn assert_zero_valid<T>();
+    {IValue::ASSERT_ZERO_VALID, {1, {}, IRT::Unit}},
 };
 
 IntrinsicCheckResult
diff --git a/gcc/rust/util/rust-intrinsic-values.h b/gcc/rust/util/rust-intrinsic-values.h
index d79326459116..f6e36a3867d4 100644
--- a/gcc/rust/util/rust-intrinsic-values.h
+++ b/gcc/rust/util/rust-intrinsic-values.h
@@ -161,6 +161,7 @@ public:
   static constexpr auto &BLACK_BOX = "black_box";
   static constexpr auto &ARITH_OFFSET = "arith_offset";
   static constexpr auto &WRITE_BYTES = "write_bytes";
+  static constexpr auto &ASSERT_ZERO_VALID = "assert_zero_valid";
 };
 } // namespace Values
 } // namespace Rust
diff --git a/gcc/testsuite/rust/compile/assert_zero_valid.rs b/gcc/testsuite/rust/compile/assert_zero_valid.rs
new file mode 100644
index 000000000000..afcb11e37080
--- /dev/null
+++ b/gcc/testsuite/rust/compile/assert_zero_valid.rs
@@ -0,0 +1,16 @@
+#![feature(intrinsics, no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+extern "rust-intrinsic" {
+    fn assert_zero_valid<T>();
+}
+
+fn main() {
+    unsafe {
+        assert_zero_valid::<i32>();
+        assert_zero_valid::<&i32>();
+    }
+}
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.