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 ¶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 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>(); + } +}
