Skip to content

Commit

Permalink
gccrs: add variant_count intrinsic
Browse files Browse the repository at this point in the history
Addresses #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 <[email protected]>
  • Loading branch information
philberty authored and dkm committed Feb 27, 2025
1 parent 3113e21 commit fe915d7
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 1 deletion.
56 changes: 55 additions & 1 deletion gcc/rust/backend/rust-compile-intrinsic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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) {}

Expand Down Expand Up @@ -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, &param_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
25 changes: 25 additions & 0 deletions gcc/testsuite/rust/execute/torture/enum_intrinsics2.rs
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit fe915d7

Please sign in to comment.