From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id 110D53858D28; Sun, 5 Mar 2023 11:42:10 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 110D53858D28 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1678016530; bh=AynYvvuZO0MqqRd3EEfZeu28HZSae62RJU00VTh5pzo=; h=From:To:Subject:Date:From; b=FGJLw0V+vcTKy834aDWFkelHrRK2cEplNL6C+8tp8+yOb5ErAmqaf4PZBZVd42dFy OSt5ZdYJ4exPUV7GuobS95X0GZDOkeozkaQOKnojCTScbX4Cur5oilz6Q/thKZoR7K mK1t1nN2Gny8+7mMd/Ol86Y/aqyYBEfcN2/NPRwo= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] gccrs: add uninit intrinsic X-Act-Checkin: gcc X-Git-Author: Philip Herron X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: baf5c546b59058fcc5aac430e8fbe6e99d355634 X-Git-Newrev: 32a9736ef6ea85993a95cd038cf1712378172fb8 Message-Id: <20230305114210.110D53858D28@sourceware.org> Date: Sun, 5 Mar 2023 11:42:10 +0000 (GMT) List-Id: https://gcc.gnu.org/g:32a9736ef6ea85993a95cd038cf1712378172fb8 commit 32a9736ef6ea85993a95cd038cf1712378172fb8 Author: Philip Herron 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 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::mapget_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(); + rust_assert (fntype->get_num_substitutions () == 1); + auto ¶m_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; + } +} + +mod mem { + pub unsafe fn uninitialized() -> 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::() } + } +}