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, ¶m_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 } +}
