From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id E0F003858417; Wed, 2 Nov 2022 09:39:50 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E0F003858417 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1667381990; bh=EigG9b1gY3bnE6fADDKUPaSgI94icphCyftAOzjbT20=; h=From:To:Subject:Date:From; b=Cw+5NAC5oQS3q0NeSYtYmwvads90G9Z6pc7GbztwnhI6rSjDpJN9rlrqmVPyY2FfW zWvrIc6D/B8qIVO0/piKf/oiuwhRQpMG2BCyDep1QEeFGlbTVidPib0QD+bys4H3HV eEZI/YofoMeKwSjO0yzXXRK5hWzB0hyAA9Wg1dJE= 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] intrinsics: Implement atomic_load intrinsics X-Act-Checkin: gcc X-Git-Author: Arthur Cohen X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: 0e08acbf2c5747089eb278f8b2addf161077322e X-Git-Newrev: b0bde7e2b5bafb111552e634b520cd908a767554 Message-Id: <20221102093950.E0F003858417@sourceware.org> Date: Wed, 2 Nov 2022 09:39:50 +0000 (GMT) List-Id: https://gcc.gnu.org/g:b0bde7e2b5bafb111552e634b520cd908a767554 commit b0bde7e2b5bafb111552e634b520cd908a767554 Author: Arthur Cohen Date: Wed Oct 26 17:00:55 2022 +0200 intrinsics: Implement atomic_load intrinsics This commit also comments out the definition of the generic atomic_store builtins, with an explanation as to why Co-authored-by: Marc Poulhies Diff: --- gcc/rust/backend/rust-builtins.cc | 56 ++++++++------ gcc/rust/backend/rust-compile-intrinsic.cc | 88 ++++++++++++++++++++-- gcc/testsuite/rust/compile/torture/intrinsics-3.rs | 2 - gcc/testsuite/rust/execute/torture/atomic_load.rs | 31 ++++++++ 4 files changed, 144 insertions(+), 33 deletions(-) diff --git a/gcc/rust/backend/rust-builtins.cc b/gcc/rust/backend/rust-builtins.cc index 64e06e1a240..66b3becc47a 100644 --- a/gcc/rust/backend/rust-builtins.cc +++ b/gcc/rust/backend/rust-builtins.cc @@ -71,36 +71,42 @@ BuiltinsContext::setup_math_fns () void BuiltinsContext::setup_atomic_fns () { - define_builtin ("atomic_store", BUILT_IN_ATOMIC_STORE, "__atomic_store", NULL, - build_function_type_list (void_type_node, size_type_node, - build_pointer_type (void_type_node), - const_ptr_type_node, - integer_type_node, NULL_TREE), - 0); - define_builtin ("atomic_store_n", BUILT_IN_ATOMIC_STORE_N, "__atomic_store_n", - NULL, - build_varargs_function_type_list (void_type_node, NULL_TREE), - 0); + auto atomic_store_type + = build_varargs_function_type_list (void_type_node, NULL_TREE); + auto atomic_load_type = [] (tree ret_type_node) { + return build_function_type_list (ret_type_node, + ptr_type_node, // const_ptr_type_node? + integer_type_node, NULL_TREE); + }; + + // FIXME: These should be the definition for the generic version of the + // atomic_store builtins, but I cannot get them to work properly. Revisit + // later. define_builtin ("atomic_store", BUILT_IN_ATOMIC_STORE, + // "__atomic_store", NULL, + // atomic_store_type, 0); + // define_builtin ("atomic_store_n", BUILT_IN_ATOMIC_STORE_N, + // "__atomic_store_n", + // NULL, atomic_store_type, 0); + define_builtin ("atomic_store_1", BUILT_IN_ATOMIC_STORE_1, "__atomic_store_1", - NULL, - build_varargs_function_type_list (void_type_node, NULL_TREE), - 0); + NULL, atomic_store_type, 0); define_builtin ("atomic_store_2", BUILT_IN_ATOMIC_STORE_2, "__atomic_store_2", - NULL, - build_varargs_function_type_list (void_type_node, NULL_TREE), - 0); + NULL, atomic_store_type, 0); define_builtin ("atomic_store_4", BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", - NULL, - build_varargs_function_type_list (void_type_node, NULL_TREE), - 0); + NULL, atomic_store_type, 0); define_builtin ("atomic_store_8", BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", - NULL, - build_varargs_function_type_list (void_type_node, NULL_TREE), - 0); + NULL, atomic_store_type, 0); define_builtin ("atomic_store_16", BUILT_IN_ATOMIC_STORE_16, - "__atomic_store_16", NULL, - build_varargs_function_type_list (void_type_node, NULL_TREE), - 0); + "__atomic_store_16", NULL, atomic_store_type, 0); + + define_builtin ("atomic_load_1", BUILT_IN_ATOMIC_LOAD_1, "__atomic_load_1", + NULL, atomic_load_type (integer_type_node), 0); + define_builtin ("atomic_load_2", BUILT_IN_ATOMIC_LOAD_2, "__atomic_load_2", + NULL, atomic_load_type (integer_type_node), 0); + define_builtin ("atomic_load_4", BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", + NULL, atomic_load_type (integer_type_node), 0); + define_builtin ("atomic_load_8", BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", + NULL, atomic_load_type (integer_type_node), 0); } void diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index b0c6015bee2..55222116366 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -120,6 +120,8 @@ prefetch_write_data (Context *ctx, TyTy::FnType *fntype) static tree atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering); +static tree +atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering); static inline std::function atomic_store_handler (int ordering) @@ -129,6 +131,14 @@ atomic_store_handler (int ordering) }; } +static inline std::function +atomic_load_handler (int ordering) +{ + return [ordering] (Context *ctx, TyTy::FnType *fntype) { + return atomic_load_handler_inner (ctx, fntype, ordering); + }; +} + static inline tree unchecked_op_inner (Context *ctx, TyTy::FnType *fntype, tree_code op); @@ -140,7 +150,7 @@ unchecked_op_handler (tree_code op) }; } -static inline tree +inline tree sorry_handler (Context *ctx, TyTy::FnType *fntype) { rust_sorry_at (fntype->get_locus (), "intrinsic %qs is not yet implemented", @@ -163,11 +173,14 @@ static const std::map allowed_types = { {"i8", "1"}, {"i16", "2"}, {"i32", "4"}, {"i64", "8"}, @@ -679,7 +693,7 @@ build_atomic_builtin_name (Location locus, TyTy::BaseType *operand_type) // TODO: Can we maybe get the generic version (atomic_store_n) to work... This // would be so much better - std::string result = "atomic_store_"; + std::string result = prefix; auto type_name = operand_type->get_name (); if (type_name == "usize" || type_name == "isize") @@ -735,7 +749,8 @@ atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering) = fntype->get_substs ()[0].get_param_ty ()->resolve (); auto builtin_name - = build_atomic_builtin_name (fntype->get_locus (), monomorphized_type); + = build_atomic_builtin_name ("atomic_store_", fntype->get_locus (), + monomorphized_type); if (builtin_name.empty ()) return error_mark_node; @@ -751,7 +766,6 @@ atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering) = ctx->get_backend ()->call_expression (atomic_store, {dst, value, memorder}, nullptr, Location ()); - TREE_READONLY (store_call) = 0; TREE_SIDE_EFFECTS (store_call) = 1; @@ -761,6 +775,68 @@ atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering) return fndecl; } +static tree +atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering) +{ + rust_assert (fntype->get_params ().size () == 1); + rust_assert (fntype->get_num_substitutions () == 1); + + tree lookup = NULL_TREE; + if (check_for_cached_intrinsic (ctx, fntype, &lookup)) + return lookup; + + auto fndecl = compile_intrinsic_function (ctx, fntype); + + // Most intrinsic functions are pure but not the atomic ones + // FIXME: Is atomic_load_* pure? Feels like it shouldn't so + TREE_READONLY (fndecl) = 0; + TREE_SIDE_EFFECTS (fndecl) = 1; + + // setup the params + std::vector param_vars; + std::vector types; + compile_fn_params (ctx, fntype, fndecl, ¶m_vars, &types); + + auto ok = ctx->get_backend ()->function_set_parameters (fndecl, param_vars); + rust_assert (ok); + + enter_intrinsic_block (ctx, fndecl); + + auto src = ctx->get_backend ()->var_expression (param_vars[0], Location ()); + auto memorder = make_unsigned_long_tree (ctx, ordering); + + auto monomorphized_type + = fntype->get_substs ()[0].get_param_ty ()->resolve (); + + auto builtin_name + = build_atomic_builtin_name ("atomic_load_", fntype->get_locus (), + monomorphized_type); + if (builtin_name.empty ()) + return error_mark_node; + + tree atomic_load_raw = nullptr; + BuiltinsContext::get ().lookup_simple_builtin (builtin_name, + &atomic_load_raw); + rust_assert (atomic_load_raw); + + auto atomic_load + = build_fold_addr_expr_loc (Location ().gcc_location (), atomic_load_raw); + + auto load_call + = ctx->get_backend ()->call_expression (atomic_load, {src, memorder}, + nullptr, Location ()); + auto return_statement + = ctx->get_backend ()->return_statement (fndecl, {load_call}, Location ()); + + TREE_READONLY (load_call) = 0; + TREE_SIDE_EFFECTS (load_call) = 1; + + ctx->add_statement (return_statement); + finalize_intrinsic_block (ctx, fndecl); + + return fndecl; +} + static inline tree unchecked_op_inner (Context *ctx, TyTy::FnType *fntype, tree_code op) { diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-3.rs b/gcc/testsuite/rust/compile/torture/intrinsics-3.rs index 1acb3533c08..5c131bd8aa2 100644 --- a/gcc/testsuite/rust/compile/torture/intrinsics-3.rs +++ b/gcc/testsuite/rust/compile/torture/intrinsics-3.rs @@ -1,9 +1,7 @@ extern "rust-intrinsic" { fn not_an_intrinsic(); - fn atomic_load(); // { dg-message "sorry, unimplemented: intrinsic .atomic_load. is not yet implemented" } } fn main() { unsafe { not_an_intrinsic() }; // { dg-error "unknown builtin intrinsic: not_an_intrinsic" } - unsafe { atomic_load() }; } diff --git a/gcc/testsuite/rust/execute/torture/atomic_load.rs b/gcc/testsuite/rust/execute/torture/atomic_load.rs new file mode 100644 index 00000000000..28ed8ae78f1 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/atomic_load.rs @@ -0,0 +1,31 @@ +trait Copy {} + +extern "rust-intrinsic" { + pub fn atomic_load_seqcst(src: *const T) -> T; + pub fn atomic_load_acquire(src: *const T) -> T; + pub fn atomic_load_relaxed(src: *const T) -> T; + pub fn atomic_load_unordered(src: *const T) -> T; +} + +fn main() -> i32 { + let one; + let two; + let three; + let four; + + unsafe { + let mut src = 1; + one = atomic_load_seqcst(&src); + + src = 2; + two = atomic_load_acquire(&src); + + src = 3; + three = atomic_load_relaxed(&src); + + src = 4; + four = atomic_load_unordered(&src); + } + + (four + three + two + one) - 10 +}