diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index bc99ef942631..ed70308fa3a5 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -92,6 +92,8 @@ static tree move_val_init_handler (Context *ctx, TyTy::FnType *fntype); static tree assume_handler (Context *ctx, TyTy::FnType *fntype); +static tree +ctpop_hander (Context *ctx, TyTy::FnType *fntype); enum class Prefetch { @@ -241,6 +243,7 @@ static const std::mapget_params ().size () == 1); + + tree lookup = NULL_TREE; + if (check_for_cached_intrinsic (ctx, fntype, &lookup)) + return lookup; + + auto fndecl = compile_intrinsic_function (ctx, fntype); + + // setup the params + std::vector param_vars; + compile_fn_params (ctx, fntype, fndecl, ¶m_vars); + + auto &x_param = param_vars.at (0); + + if (!Backend::function_set_parameters (fndecl, param_vars)) + return error_mark_node; + + 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); + + tree tmp_stmt = error_mark_node; + Bvariable *result_variable + = Backend::temporary_variable (fndecl, NULL_TREE, template_parameter_type, + NULL_TREE, true /*address_is_taken*/, + UNDEF_LOCATION, &tmp_stmt); + + enter_intrinsic_block (ctx, fndecl, {result_variable}); + + // BUILTIN popcount FN BODY BEGIN + auto x = Backend::var_expression (x_param, UNDEF_LOCATION); + + tree popcount_builtin = error_mark_node; + + BuiltinsContext::get ().lookup_simple_builtin ("__builtin_popcountg", + &popcount_builtin); + rust_assert (popcount_builtin != error_mark_node); + + tree builtin_call + = build_call_expr_loc (BUILTINS_LOCATION, popcount_builtin, 1, x); + + auto return_statement + = Backend::return_statement (fndecl, + build1 (CONVERT_EXPR, unsigned_type_node, + builtin_call), + UNDEF_LOCATION); + ctx->add_statement (return_statement); + + // BUILTIN popcount FN BODY END + + finalize_intrinsic_block (ctx, fndecl); + + return fndecl; +} + /** * pub fn add_with_overflow(x: T, y: T) -> (T, bool); */ diff --git a/gcc/testsuite/rust/execute/torture/ctpop.rs b/gcc/testsuite/rust/execute/torture/ctpop.rs new file mode 100644 index 000000000000..15aa67583b3c --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/ctpop.rs @@ -0,0 +1,19 @@ +#![feature(intrinsics)] + +#[lang = "sized"] +pub trait Sized {} + +extern "rust-intrinsic" { + pub fn ctpop(x: T) -> u32; +} + +fn main() -> i32 { + let pop1 = ctpop(42i32) - 3; + let pop2 = ctpop(42u32) - 3; + let pop3 = ctpop(42i64) - 3; + let pop4 = ctpop(42u64) - 3; + let pop5 = ctpop(-42i32) - 29; + let pop6 = ctpop(0x1234567812345678i64) - 26; + let pop7 = ctpop(-1i64) - 64; + (pop1 + pop2 + pop3 + pop4 + pop5 + pop6 + pop7) as i32 +}