aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend
diff options
context:
space:
mode:
authorPhilip Herron <herron.philip@googlemail.com>2025-02-11 17:42:24 +0000
committerArthur Cohen <arthur.cohen@embecosm.com>2025-03-24 13:07:04 +0100
commitfc77cd5387503ff4aaf2fdf37e05f156cb86c1ea (patch)
tree04cbc0fba835d7668277216dfbc2ec1c84f2eab9 /gcc/rust/backend
parentb5106eeabdb5ebcd4bb6b2fa5dbb6932b9f406f6 (diff)
downloadgcc-fc77cd5387503ff4aaf2fdf37e05f156cb86c1ea.zip
gcc-fc77cd5387503ff4aaf2fdf37e05f156cb86c1ea.tar.gz
gcc-fc77cd5387503ff4aaf2fdf37e05f156cb86c1ea.tar.bz2
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 <herron.philip@googlemail.com>
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r--gcc/rust/backend/rust-compile-intrinsic.cc56
1 files changed, 55 insertions, 1 deletions
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index 1f93e82..28c69d5 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, &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