diff options
author | Philip Herron <herron.philip@googlemail.com> | 2023-03-01 12:43:56 +0000 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2023-03-02 16:35:59 +0000 |
commit | 32a9736ef6ea85993a95cd038cf1712378172fb8 (patch) | |
tree | 181990151427bae94f128d8e3be51bfd12121ec5 /gcc/rust | |
parent | baf5c546b59058fcc5aac430e8fbe6e99d355634 (diff) | |
download | gcc-32a9736ef6ea85993a95cd038cf1712378172fb8.zip gcc-32a9736ef6ea85993a95cd038cf1712378172fb8.tar.gz gcc-32a9736ef6ea85993a95cd038cf1712378172fb8.tar.bz2 |
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.
Diffstat (limited to 'gcc/rust')
-rw-r--r-- | gcc/rust/backend/rust-builtins.cc | 6 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-intrinsic.cc | 56 |
2 files changed, 62 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-builtins.cc b/gcc/rust/backend/rust-builtins.cc index 0517a9a..c96553b 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 04b0d3a..85f6e1c 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 ¶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 |