From: Philip Herron Date: Tue, 11 Feb 2025 17:42:24 +0000 (+0000) Subject: gccrs: add variant_count intrinsic X-Git-Tag: basepoints/gcc-16~759 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fc77cd5387503ff4aaf2fdf37e05f156cb86c1ea;p=thirdparty%2Fgcc.git gccrs: add variant_count intrinsic 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 --- 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::mapget_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 (); + if (is_adt) + { + const auto &adt = *static_cast (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 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() -> usize; + } + } +} + +pub fn main() -> i32 { + let count = core::intrinsics::variant_count::(); + + (count as i32) - 3 +}