From: Enes Cevik <[email protected]>
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]>
---
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/bfa07ecd56171c68da6ba987ab490dbddb7c3fec
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/4620
gcc/rust/backend/rust-compile-intrinsic.cc | 1 +
gcc/rust/backend/rust-intrinsic-handlers.cc | 70 +++++++++++++++++++
gcc/rust/backend/rust-intrinsic-handlers.h | 3 +
.../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(+)
create mode 100644 gcc/testsuite/rust/execute/write-bytes.rs
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc
b/gcc/rust/backend/rust-compile-intrinsic.cc
index a00b2a50e..51531de3c 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 8ea93d7f7..24f831ec7 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 34e9f49d7..c088f9ff4 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 8f51cf135..af27a2ddb 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 1c275e7b7..10c5c1eb2 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 000000000..bc8fd8f46
--- /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 }
+}
base-commit: f1677688901c1e3ddadc941a89bfd1f7b8e2469e
--
2.54.0