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]>
---
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/064dddd85984adb7d47ad2d552d70c1295fcdbe8
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/4697
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 205bf4113..b48647670 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 b119593b8..6069898da 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 ¶m_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 8916c59f3..712d422e5 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 df596c58a..a0a047963 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 d79326459..f6e36a386 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 000000000..afcb11e37
--- /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>();
+ }
+}
base-commit: 7cc595fafff3bafc115127818a0b890194ff84c0
--
2.54.0