public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] gccrs: add uninit intrinsic
@ 2023-03-05 11:42 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2023-03-05 11:42 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:32a9736ef6ea85993a95cd038cf1712378172fb8

commit 32a9736ef6ea85993a95cd038cf1712378172fb8
Author: Philip Herron <herron.philip@googlemail.com>
Date:   Wed Mar 1 12:43:56 2023 +0000

    gccrs: add uninit intrinsic
    
    Following an investigation from rustc and discussions on zulip the
    recommendation was that for uninit we memset to 0x01 which is less likely
    to be a null ptr but still an invalid reference.
    
    Fixes #1899
    
    Signed-off-by: Philip Herron <herron.philip@googlemail.com>
    
    gcc/rust/ChangeLog:
    
            * backend/rust-builtins.cc (BuiltinsContext::setup): add memset builtin to the map
            * backend/rust-compile-intrinsic.cc (uninit_handler): implement uninit intrinsic
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/torture/uninit-intrinsic-1.rs: New test.

Diff:
---
 gcc/rust/backend/rust-builtins.cc                  |  6 +++
 gcc/rust/backend/rust-compile-intrinsic.cc         | 56 ++++++++++++++++++++++
 .../rust/compile/torture/uninit-intrinsic-1.rs     | 21 ++++++++
 3 files changed, 83 insertions(+)

diff --git a/gcc/rust/backend/rust-builtins.cc b/gcc/rust/backend/rust-builtins.cc
index 0517a9aeaf0..c96553b8c59 100644
--- a/gcc/rust/backend/rust-builtins.cc
+++ b/gcc/rust/backend/rust-builtins.cc
@@ -249,6 +249,12 @@ BuiltinsContext::setup ()
 					    size_type_node, NULL_TREE),
 		  0);
 
+  define_builtin ("memset", BUILT_IN_MEMSET, "__builtin_memset", "memset",
+		  build_function_type_list (void_type_node, ptr_type_node,
+					    integer_type_node, size_type_node,
+					    NULL_TREE),
+		  0);
+
   define_builtin ("prefetch", BUILT_IN_PREFETCH, "__builtin_prefetch",
 		  "prefetch",
 		  build_varargs_function_type_list (
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index 04b0d3a2611..85f6e1c63d2 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -81,6 +81,8 @@ static tree
 copy_nonoverlapping_handler (Context *ctx, TyTy::FnType *fntype);
 static tree
 op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, tree_code op);
+static tree
+uninit_handler (Context *ctx, TyTy::FnType *fntype);
 
 enum class Prefetch
 {
@@ -202,6 +204,7 @@ static const std::map<std::string,
     {"unchecked_rem", unchecked_op_handler (TRUNC_MOD_EXPR)},
     {"unchecked_shl", unchecked_op_handler (LSHIFT_EXPR)},
     {"unchecked_shr", unchecked_op_handler (RSHIFT_EXPR)},
+    {"uninit", uninit_handler},
 };
 
 Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
@@ -986,5 +989,58 @@ unchecked_op_inner (Context *ctx, TyTy::FnType *fntype, tree_code op)
   return fndecl;
 }
 
+static tree
+uninit_handler (Context *ctx, TyTy::FnType *fntype)
+{
+  // uninit has _zero_ parameters its parameter is the generic one
+  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);
+
+  // get the template parameter type tree fn size_of<T>();
+  rust_assert (fntype->get_num_substitutions () == 1);
+  auto &param_mapping = fntype->get_substs ().at (0);
+  const TyTy::ParamType *param_tyty = param_mapping.get_param_ty ();
+  TyTy::BaseType *resolved_tyty = param_tyty->resolve ();
+  tree template_parameter_type
+    = TyTyResolveCompile::compile (ctx, resolved_tyty);
+
+  enter_intrinsic_block (ctx, fndecl);
+
+  // BUILTIN size_of FN BODY BEGIN
+
+  tree memset_builtin = error_mark_node;
+  BuiltinsContext::get ().lookup_simple_builtin ("memset", &memset_builtin);
+  rust_assert (memset_builtin != error_mark_node);
+
+  // call memset with 0x01 and size of the thing see
+  // https://github.com/Rust-GCC/gccrs/issues/1899
+
+  tree dst = DECL_RESULT (fndecl);
+  tree constant_byte = build_int_cst (integer_type_node, 0x01);
+  tree size_expr = TYPE_SIZE_UNIT (template_parameter_type);
+
+  tree memset_call = build_call_expr_loc (BUILTINS_LOCATION, memset_builtin, 3,
+					  dst, constant_byte, size_expr);
+  TREE_READONLY (memset_call) = 0;
+  TREE_SIDE_EFFECTS (memset_call) = 1;
+
+  ctx->add_statement (memset_call);
+
+  auto return_statement
+    = ctx->get_backend ()->return_statement (fndecl, {DECL_RESULT (fndecl)},
+					     Location ());
+  ctx->add_statement (return_statement);
+  // BUILTIN size_of FN BODY END
+
+  finalize_intrinsic_block (ctx, fndecl);
+
+  return fndecl;
+}
+
 } // namespace Compile
 } // namespace Rust
diff --git a/gcc/testsuite/rust/compile/torture/uninit-intrinsic-1.rs b/gcc/testsuite/rust/compile/torture/uninit-intrinsic-1.rs
new file mode 100644
index 00000000000..0c6772b5f38
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/uninit-intrinsic-1.rs
@@ -0,0 +1,21 @@
+mod intrinsics {
+    extern "rust-intrinsic" {
+        pub fn uninit<T>() -> T;
+    }
+}
+
+mod mem {
+    pub unsafe fn uninitialized<T>() -> T {
+        intrinsics::uninit()
+    }
+}
+
+struct Foo(i32, i32);
+// { dg-warning "struct is never constructed: .Foo." "" { target *-*-* } .-1 }
+// FIXME ^^ above is a bad-warning
+
+impl Foo {
+    pub fn new() -> Self {
+        unsafe { mem::uninitialized::<Foo>() }
+    }
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-03-05 11:42 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-05 11:42 [gcc/devel/rust/master] gccrs: add uninit intrinsic Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).