[COMMITTED 40/77] gccrs: intrinsic: Add assert_zero_valid

[email protected]
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.rust
Message-ID <[email protected]>
From: Enes Cevik <[email protected]>

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]>
---
 gcc/rust/backend/rust-compile-intrinsic.cc    |  1 +
 gcc/rust/backend/rust-intrinsic-handlers.cc   | 51 +++++++++++++++++++
 gcc/rust/backend/rust-intrinsic-handlers.h    |  2 +
 .../rust-hir-type-check-intrinsic.cc          |  3 +-
 gcc/rust/util/rust-intrinsic-values.h         |  1 +
 .../rust/compile/assert_zero_valid.rs         | 16 ++++++
 6 files changed, 73 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/compile/assert_zero_valid.rs

diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index 205bf411396..b4864767008 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 b119593b8a9..6069898da74 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 8916c59f39c..712d422e514 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 df596c58a4e..a0a0479639e 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 d7932645911..f6e36a3867d 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 00000000000..afcb11e3708
--- /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>();
+    }
+}
-- 
2.50.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.