From: Philip Herron <herron.phi...@googlemail.com> Addresses Rust-GCC#3348
gcc/rust/ChangeLog: * backend/rust-compile-intrinsic.cc (variant_count_handler): new intrinsic gcc/testsuite/ChangeLog: * rust/execute/torture/enum_intrinsics2.rs: New test. Signed-off-by: Philip Herron <herron.phi...@googlemail.com> --- gcc/rust/backend/rust-compile-intrinsic.cc | 56 ++++++++++++++++++- .../rust/execute/torture/enum_intrinsics2.rs | 25 +++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/rust/execute/torture/enum_intrinsics2.rs diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index 1f93e82a93a..28c69d50b46 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -90,6 +90,8 @@ static tree assume_handler (Context *ctx, TyTy::FnType *fntype); static tree discriminant_value_handler (Context *ctx, TyTy::FnType *fntype); +static tree +variant_count_handler (Context *ctx, TyTy::FnType *fntype); enum class Prefetch { @@ -252,7 +254,8 @@ static const std::map<std::string, {"assume", assume_handler}, {"try", try_handler (false)}, {"catch_unwind", try_handler (true)}, - {"discriminant_value", discriminant_value_handler}}; + {"discriminant_value", discriminant_value_handler}, + {"variant_count", variant_count_handler}}; Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {} @@ -1436,5 +1439,56 @@ discriminant_value_handler (Context *ctx, TyTy::FnType *fntype) return fndecl; } +static tree +variant_count_handler (Context *ctx, TyTy::FnType *fntype) +{ + rust_assert (fntype->get_num_type_params () == 1); + auto &mapping = fntype->get_substs ().at (0); + auto param_ty = mapping.get_param_ty (); + rust_assert (param_ty->can_resolve ()); + auto resolved = param_ty->resolve (); + + size_t variant_count = 0; + bool is_adt = resolved->is<TyTy::ADTType> (); + if (is_adt) + { + const auto &adt = *static_cast<TyTy::ADTType *> (resolved); + variant_count = adt.number_of_variants (); + } + + tree lookup = NULL_TREE; + if (check_for_cached_intrinsic (ctx, fntype, &lookup)) + return lookup; + + auto fndecl = compile_intrinsic_function (ctx, fntype); + + std::vector<Bvariable *> param_vars; + compile_fn_params (ctx, fntype, fndecl, ¶m_vars); + + if (!Backend::function_set_parameters (fndecl, param_vars)) + return error_mark_node; + + enter_intrinsic_block (ctx, fndecl); + + // BUILTIN disriminant_value FN BODY BEGIN + tree result_decl = DECL_RESULT (fndecl); + tree type = TREE_TYPE (result_decl); + + mpz_t ival; + mpz_init_set_ui (ival, variant_count); + tree result = wide_int_to_tree (type, wi::from_mpz (type, ival, true)); + mpz_clear (ival); + + auto return_statement + = Backend::return_statement (fndecl, result, BUILTINS_LOCATION); + ctx->add_statement (return_statement); + + // BUILTIN disriminant_value FN BODY END + + finalize_intrinsic_block (ctx, fndecl); + + return fndecl; +} + } // namespace Compile } // namespace Rust diff --git a/gcc/testsuite/rust/execute/torture/enum_intrinsics2.rs b/gcc/testsuite/rust/execute/torture/enum_intrinsics2.rs new file mode 100644 index 00000000000..c1bae35deb2 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/enum_intrinsics2.rs @@ -0,0 +1,25 @@ +#![feature(intrinsics)] + +#[lang = "sized"] +pub trait Sized {} + +enum BookFormat { + Paperback, + Hardback, + Ebook, +} + +mod core { + mod intrinsics { + extern "rust-intrinsic" { + #[rustc_const_unstable(feature = "variant_count", issue = "73662")] + pub fn variant_count<T>() -> usize; + } + } +} + +pub fn main() -> i32 { + let count = core::intrinsics::variant_count::<BookFormat>(); + + (count as i32) - 3 +} -- 2.45.2